From 53b55eb4c33ef6a2cd3477292caae6ae03bac7f8 Mon Sep 17 00:00:00 2001 From: Tim Allison Date: Thu, 21 Sep 2017 14:52:59 +0000 Subject: [PATCH] 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 --- .../poifs/poibrowser/DocumentDescriptor.java | 7 +++- .../apache/poi/ddf/EscherArrayProperty.java | 13 ++++--- .../org/apache/poi/ddf/EscherBSERecord.java | 7 +++- .../org/apache/poi/ddf/EscherBlipRecord.java | 9 +++-- .../poi/ddf/EscherClientAnchorRecord.java | 6 +++- .../poi/ddf/EscherClientDataRecord.java | 6 +++- .../apache/poi/ddf/EscherMetafileBlip.java | 7 ++-- .../org/apache/poi/ddf/EscherPictBlip.java | 5 ++- .../apache/poi/ddf/EscherPropertyFactory.java | 9 +++-- .../apache/poi/ddf/EscherTextboxRecord.java | 9 +++-- .../apache/poi/ddf/UnknownEscherRecord.java | 7 +++- src/java/org/apache/poi/hpsf/Blob.java | 7 +++- .../org/apache/poi/hpsf/ClipboardData.java | 5 ++- .../org/apache/poi/hpsf/CodePageString.java | 6 +++- src/java/org/apache/poi/hpsf/Section.java | 6 +++- .../org/apache/poi/hpsf/UnicodeString.java | 5 ++- .../org/apache/poi/hpsf/VariantSupport.java | 8 +++-- .../poi/hssf/extractor/OldExcelExtractor.java | 5 ++- .../poi/hssf/record/CFRule12Record.java | 17 +++++---- .../apache/poi/hssf/record/DConRefRecord.java | 10 ++++-- .../record/EmbeddedObjectRefSubRecord.java | 6 +++- .../poi/hssf/record/EscherAggregate.java | 6 +++- .../poi/hssf/record/FtCblsSubRecord.java | 3 +- .../poi/hssf/record/GroupMarkerSubRecord.java | 6 +++- .../poi/hssf/record/HyperlinkRecord.java | 6 +++- .../hssf/record/NoteStructureSubRecord.java | 3 +- .../poi/hssf/record/OldLabelRecord.java | 5 ++- .../poi/hssf/record/OldSheetRecord.java | 7 +++- .../poi/hssf/record/OldStringRecord.java | 7 +++- .../poi/hssf/record/RecordInputStream.java | 7 +++- .../org/apache/poi/hssf/record/SubRecord.java | 7 +++- .../poi/hssf/record/common/UnicodeString.java | 7 +++- .../record/crypto/Biff8DecryptingStream.java | 5 ++- .../poi/hssf/usermodel/HSSFWorkbook.java | 7 +++- .../poifs/crypt/ChunkedCipherInputStream.java | 9 +++-- .../crypt/ChunkedCipherOutputStream.java | 7 ++-- .../poi/poifs/crypt/CryptoFunctions.java | 7 +++- .../poi/poifs/crypt/DataSpaceMapUtils.java | 7 +++- .../org/apache/poi/poifs/dev/POIFSDump.java | 6 +++- .../poifs/filesystem/DocumentInputStream.java | 1 + .../filesystem/NDocumentInputStream.java | 3 +- .../poi/poifs/filesystem/NPOIFSDocument.java | 11 ++++-- .../poifs/filesystem/NPOIFSFileSystem.java | 8 +++-- .../poi/poifs/filesystem/Ole10Native.java | 10 ++++-- .../poifs/nio/ByteArrayBackedDataSource.java | 8 ++++- .../poi/poifs/property/NPropertyTable.java | 6 +++- .../poi/poifs/storage/DocumentBlock.java | 6 +++- .../apache/poi/poifs/storage/HeaderBlock.java | 8 +++-- .../poi/poifs/storage/RawDataBlock.java | 5 ++- .../org/apache/poi/ss/formula/Formula.java | 6 +++- .../function/FunctionMetadataReader.java | 6 +++- src/java/org/apache/poi/util/IOUtils.java | 35 ++++++++++++++++--- .../org/apache/poi/util/LZWDecompresser.java | 6 +++- .../org/apache/poi/util/LittleEndian.java | 28 +++++++++++++++ src/java/org/apache/poi/util/StringUtil.java | 7 ++-- .../poi/poifs/crypt/agile/AgileEncryptor.java | 15 +++++--- .../poi/ss/extractor/EmbeddedExtractor.java | 6 ++-- .../poi/xslf/usermodel/XMLSlideShow.java | 4 ++- .../apache/poi/xssf/binary/XSSFBParser.java | 7 ++-- .../apache/poi/hdgf/chunks/ChunkFactory.java | 8 ++++- .../hdgf/streams/CompressedStreamStore.java | 7 +++- .../apache/poi/hdgf/streams/StreamStore.java | 9 +++-- .../poi/hemf/record/HemfCommentEMFPlus.java | 2 +- .../poi/hemf/record/HemfCommentPublic.java | 2 +- .../poi/hemf/record/HemfCommentRecord.java | 2 +- .../apache/poi/hemf/record/HemfHeader.java | 2 +- .../org/apache/poi/hemf/record/HemfText.java | 2 +- .../poi/hmef/attribute/MAPIAttribute.java | 16 ++++++--- .../poi/hmef/attribute/MAPIRtfAttribute.java | 7 +++- .../poi/hmef/attribute/TNEFAttribute.java | 6 +++- .../org/apache/poi/hmef/dev/HMEFDumper.java | 7 +++- .../org/apache/poi/hpbf/model/EscherPart.java | 7 +++- .../apache/poi/hpbf/model/QuillContents.java | 5 ++- .../poi/hpbf/model/qcbits/QCTextBit.java | 7 +++- .../src/org/apache/poi/hslf/blip/Bitmap.java | 3 +- .../src/org/apache/poi/hslf/blip/DIB.java | 9 +++-- .../org/apache/poi/hslf/dev/PPTXMLDump.java | 6 +++- .../apache/poi/hslf/dev/SlideShowDumper.java | 8 +++-- .../poi/hslf/record/AnimationInfoAtom.java | 6 +++- .../org/apache/poi/hslf/record/CString.java | 7 +++- .../poi/hslf/record/Comment2000Atom.java | 7 +++- .../poi/hslf/record/CurrentUserAtom.java | 15 ++++---- .../apache/poi/hslf/record/DocumentAtom.java | 6 +++- .../apache/poi/hslf/record/ExEmbedAtom.java | 6 +++- .../poi/hslf/record/ExHyperlinkAtom.java | 7 +++- .../apache/poi/hslf/record/ExMediaAtom.java | 5 ++- .../apache/poi/hslf/record/ExObjListAtom.java | 7 +++- .../apache/poi/hslf/record/ExOleObjAtom.java | 6 +++- .../apache/poi/hslf/record/ExOleObjStg.java | 6 +++- .../poi/hslf/record/FontEntityAtom.java | 9 +++-- .../record/HSLFEscherClientDataRecord.java | 6 +++- .../poi/hslf/record/HeadersFootersAtom.java | 7 +++- .../poi/hslf/record/InteractiveInfoAtom.java | 7 +++- .../poi/hslf/record/MasterTextPropAtom.java | 9 +++-- .../org/apache/poi/hslf/record/NotesAtom.java | 7 +++- .../org/apache/poi/hslf/record/PPDrawing.java | 8 ++++- .../poi/hslf/record/PPDrawingGroup.java | 7 +++- .../poi/hslf/record/PersistPtrHolder.java | 7 +++- .../org/apache/poi/hslf/record/SlideAtom.java | 8 +++-- .../poi/hslf/record/SlidePersistAtom.java | 7 +++- .../org/apache/poi/hslf/record/SoundData.java | 7 +++- .../poi/hslf/record/StyleTextProp9Atom.java | 7 +++- .../poi/hslf/record/StyleTextPropAtom.java | 10 ++++-- .../apache/poi/hslf/record/TextBytesAtom.java | 6 +++- .../apache/poi/hslf/record/TextCharsAtom.java | 8 +++-- .../apache/poi/hslf/record/TextRulerAtom.java | 7 +++- .../poi/hslf/record/TextSpecInfoAtom.java | 7 +++- .../poi/hslf/record/TextSpecInfoRun.java | 6 +++- .../hslf/record/TxInteractiveInfoAtom.java | 7 +++- .../poi/hslf/record/TxMasterStyleAtom.java | 5 ++- .../hslf/record/UnknownRecordPlaceholder.java | 7 +++- .../poi/hslf/usermodel/HSLFSlideShow.java | 9 +++-- .../poi/hslf/usermodel/HSLFSlideShowImpl.java | 5 ++- .../poi/hsmf/datatypes/PropertiesChunk.java | 5 ++- .../org/apache/poi/hwmf/record/HwmfText.java | 2 +- .../src/org/apache/poi/hwpf/HWPFDocument.java | 5 ++- .../org/apache/poi/hwpf/HWPFDocumentCore.java | 5 ++- .../org/apache/poi/hwpf/HWPFOldDocument.java | 7 +++- .../poi/hwpf/model/CHPFormattedDiskPage.java | 6 +++- .../poi/hwpf/model/ComplexFileTable.java | 6 +++- .../poi/hwpf/model/DocumentProperties.java | 6 +++- .../src/org/apache/poi/hwpf/model/Ffn.java | 7 +++- .../poi/hwpf/model/FileInformationBlock.java | 9 +++-- .../org/apache/poi/hwpf/model/ListLevel.java | 9 ++++- .../poi/hwpf/model/OldSectionTable.java | 3 +- .../poi/hwpf/model/OldTextPieceTable.java | 6 +++- .../poi/hwpf/model/PAPFormattedDiskPage.java | 3 +- .../poi/hwpf/model/PICFAndOfficeArtData.java | 5 ++- .../org/apache/poi/hwpf/model/PlexOfCps.java | 9 +++-- .../apache/poi/hwpf/model/SectionTable.java | 7 +++- .../poi/hwpf/model/StyleDescription.java | 7 ++-- .../apache/poi/hwpf/model/TextPieceTable.java | 8 +++-- .../org/apache/poi/hwpf/sprm/SprmBuffer.java | 9 +++-- .../org/apache/poi/hwpf/sprm/SprmUtils.java | 9 +++-- .../poi/hwpf/sprm/TableSprmCompressor.java | 8 ++++- 135 files changed, 772 insertions(+), 193 deletions(-) diff --git a/src/examples/src/org/apache/poi/poifs/poibrowser/DocumentDescriptor.java b/src/examples/src/org/apache/poi/poifs/poibrowser/DocumentDescriptor.java index 754da35ccc..d3c837a44d 100644 --- a/src/examples/src/org/apache/poi/poifs/poibrowser/DocumentDescriptor.java +++ b/src/examples/src/org/apache/poi/poifs/poibrowser/DocumentDescriptor.java @@ -19,6 +19,7 @@ package org.apache.poi.poifs.poibrowser; import java.io.*; import org.apache.poi.poifs.filesystem.*; +import org.apache.poi.util.IOUtils; /** *

Describes the most important (whatever that is) features of a @@ -26,6 +27,10 @@ import org.apache.poi.poifs.filesystem.*; */ public class DocumentDescriptor { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + String name; POIFSDocumentPath path; DocumentInputStream stream; @@ -60,7 +65,7 @@ public class DocumentDescriptor if (stream.markSupported()) { 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)); bytes = new byte[read]; System.arraycopy(b, 0, bytes, 0, read); diff --git a/src/java/org/apache/poi/ddf/EscherArrayProperty.java b/src/java/org/apache/poi/ddf/EscherArrayProperty.java index 9033a49efa..84026f5481 100644 --- a/src/java/org/apache/poi/ddf/EscherArrayProperty.java +++ b/src/java/org/apache/poi/ddf/EscherArrayProperty.java @@ -21,6 +21,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; 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. */ public final class EscherArrayProperty extends EscherComplexProperty implements Iterable { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + /** * The size of the header that goes at the * start of the array, before the data @@ -69,7 +74,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements public void setNumberOfElementsInArray(int numberOfElements) { int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; 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); setComplexData(newArray); } @@ -83,7 +88,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements public void setNumberOfElementsInMemory(int numberOfElements) { int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; if (expectedArraySize != getComplexData().length) { - byte[] newArray = new byte[expectedArraySize]; + byte[] newArray = IOUtils.safelyAllocate(expectedArraySize, MAX_RECORD_LENGTH); System.arraycopy(getComplexData(), 0, newArray, 0, expectedArraySize); setComplexData(newArray); } @@ -100,7 +105,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements int expectedArraySize = getNumberOfElementsInArray() * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; if (expectedArraySize != getComplexData().length) { // 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 ); setComplexData(newArray); } @@ -108,7 +113,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements public byte[] getElement(int index) { 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 ); return result; } diff --git a/src/java/org/apache/poi/ddf/EscherBSERecord.java b/src/java/org/apache/poi/ddf/EscherBSERecord.java index efeb3f830c..d3e0514be7 100644 --- a/src/java/org/apache/poi/ddf/EscherBSERecord.java +++ b/src/java/org/apache/poi/ddf/EscherBSERecord.java @@ -17,6 +17,7 @@ package org.apache.poi.ddf; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -27,6 +28,10 @@ import org.apache.poi.util.LittleEndian; * @see EscherBlipRecord */ 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 String RECORD_DESCRIPTION = "MsofbtBSE"; @@ -84,7 +89,7 @@ public final class EscherBSERecord extends EscherRecord { pos += 36 + bytesRead; bytesRemaining -= bytesRead; - _remainingData = new byte[bytesRemaining]; + _remainingData = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH); System.arraycopy( data, pos, _remainingData, 0, bytesRemaining ); return bytesRemaining + 8 + 36 + (field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize()) ; diff --git a/src/java/org/apache/poi/ddf/EscherBlipRecord.java b/src/java/org/apache/poi/ddf/EscherBlipRecord.java index 266c1f03b1..df49c4747e 100644 --- a/src/java/org/apache/poi/ddf/EscherBlipRecord.java +++ b/src/java/org/apache/poi/ddf/EscherBlipRecord.java @@ -17,9 +17,14 @@ package org.apache.poi.ddf; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; 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_END = (short) 0xF117; public static final String RECORD_DESCRIPTION = "msofbtBlip"; @@ -36,7 +41,7 @@ public class EscherBlipRecord extends EscherRecord { int bytesAfterHeader = readHeader( data, offset ); 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); return bytesAfterHeader + 8; @@ -94,7 +99,7 @@ public class EscherBlipRecord extends EscherRecord { if (pictureData == null || offset < 0 || length < 0 || pictureData.length < offset+length) { 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); } diff --git a/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java b/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java index b038c12d30..741ea0fdb4 100644 --- a/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java +++ b/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java @@ -17,6 +17,7 @@ package org.apache.poi.ddf; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -30,6 +31,9 @@ import org.apache.poi.util.LittleEndian; public class EscherClientAnchorRecord 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 String RECORD_DESCRIPTION = "MsofbtClientAnchor"; @@ -83,7 +87,7 @@ public class EscherClientAnchorRecord } } bytesRemaining -= size; - remainingData = new byte[bytesRemaining]; + remainingData = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH); System.arraycopy( data, pos + size, remainingData, 0, bytesRemaining ); return 8 + size + bytesRemaining; } diff --git a/src/java/org/apache/poi/ddf/EscherClientDataRecord.java b/src/java/org/apache/poi/ddf/EscherClientDataRecord.java index d84054de6b..801098854d 100644 --- a/src/java/org/apache/poi/ddf/EscherClientDataRecord.java +++ b/src/java/org/apache/poi/ddf/EscherClientDataRecord.java @@ -18,6 +18,7 @@ package org.apache.poi.ddf; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -27,6 +28,9 @@ import org.apache.poi.util.LittleEndian; public class EscherClientDataRecord 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 String RECORD_DESCRIPTION = "MsofbtClientData"; @@ -36,7 +40,7 @@ public class EscherClientDataRecord public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { int bytesRemaining = readHeader( data, offset ); int pos = offset + 8; - remainingData = new byte[bytesRemaining]; + remainingData = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH); System.arraycopy( data, pos, remainingData, 0, bytesRemaining ); return 8 + bytesRemaining; } diff --git a/src/java/org/apache/poi/ddf/EscherMetafileBlip.java b/src/java/org/apache/poi/ddf/EscherMetafileBlip.java index 5fdbae6c86..fcc6d92b05 100644 --- a/src/java/org/apache/poi/ddf/EscherMetafileBlip.java +++ b/src/java/org/apache/poi/ddf/EscherMetafileBlip.java @@ -26,12 +26,15 @@ import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; import org.apache.poi.hssf.usermodel.HSSFPictureData; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; public final class EscherMetafileBlip extends EscherBlipRecord { 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_WMF = (short) 0xF018 + 3; @@ -79,7 +82,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord { field_6_fCompression = 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 ); pos += field_5_cbSave; @@ -93,7 +96,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord { int remaining = bytesAfterHeader - pos + offset + HEADER_SIZE; if(remaining > 0) { - remainingData = new byte[remaining]; + remainingData = IOUtils.safelyAllocate(remaining, MAX_RECORD_LENGTH); System.arraycopy( data, pos, remainingData, 0, remaining ); } return bytesAfterHeader + HEADER_SIZE; diff --git a/src/java/org/apache/poi/ddf/EscherPictBlip.java b/src/java/org/apache/poi/ddf/EscherPictBlip.java index c94f56f18d..69cf60138f 100644 --- a/src/java/org/apache/poi/ddf/EscherPictBlip.java +++ b/src/java/org/apache/poi/ddf/EscherPictBlip.java @@ -24,12 +24,15 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.InflaterInputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; public final class EscherPictBlip extends EscherBlipRecord { 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_WMF = (short) 0xF018 + 3; @@ -68,7 +71,7 @@ public final class EscherPictBlip extends EscherBlipRecord { field_6_fCompression = 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 ); // 0 means DEFLATE compression diff --git a/src/java/org/apache/poi/ddf/EscherPropertyFactory.java b/src/java/org/apache/poi/ddf/EscherPropertyFactory.java index 3b05034caf..fe51c18c46 100644 --- a/src/java/org/apache/poi/ddf/EscherPropertyFactory.java +++ b/src/java/org/apache/poi/ddf/EscherPropertyFactory.java @@ -20,12 +20,17 @@ package org.apache.poi.ddf; import java.util.ArrayList; import java.util.List; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** * Generates a property given a reference into the byte array storing that property. */ 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. * @@ -64,9 +69,9 @@ public final class EscherPropertyFactory { if ( !isComplex ) { ep = new EscherSimpleProperty( propId, propData ); } else if ( propertyType == EscherPropertyMetaData.TYPE_ARRAY) { - ep = new EscherArrayProperty( propId, new byte[propData]); + ep = new EscherArrayProperty( propId, IOUtils.safelyAllocate(propData, MAX_RECORD_LENGTH)); } else { - ep = new EscherComplexProperty( propId, new byte[propData]); + ep = new EscherComplexProperty( propId, IOUtils.safelyAllocate(propData, MAX_RECORD_LENGTH)); } break; } diff --git a/src/java/org/apache/poi/ddf/EscherTextboxRecord.java b/src/java/org/apache/poi/ddf/EscherTextboxRecord.java index 07527cb960..fbf37f49b0 100644 --- a/src/java/org/apache/poi/ddf/EscherTextboxRecord.java +++ b/src/java/org/apache/poi/ddf/EscherTextboxRecord.java @@ -20,6 +20,7 @@ package org.apache.poi.ddf; import java.util.ArrayList; import java.util.List; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; 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. */ 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 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 // useful with it - thedata = new byte[bytesRemaining]; + thedata = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH); System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining ); return bytesRemaining + 8; } @@ -97,7 +102,7 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable */ 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); } diff --git a/src/java/org/apache/poi/ddf/UnknownEscherRecord.java b/src/java/org/apache/poi/ddf/UnknownEscherRecord.java index f722f87b65..38475be818 100644 --- a/src/java/org/apache/poi/ddf/UnknownEscherRecord.java +++ b/src/java/org/apache/poi/ddf/UnknownEscherRecord.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -28,6 +29,10 @@ import org.apache.poi.util.LittleEndian; * we do not explicitly support. */ 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]; /** 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; } - thedata = new byte[bytesRemaining]; + thedata = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH); System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining ); return bytesRemaining + 8; } diff --git a/src/java/org/apache/poi/hpsf/Blob.java b/src/java/org/apache/poi/hpsf/Blob.java index af207feabb..07c2c2ffe8 100644 --- a/src/java/org/apache/poi/hpsf/Blob.java +++ b/src/java/org/apache/poi/hpsf/Blob.java @@ -16,18 +16,23 @@ ==================================================================== */ package org.apache.poi.hpsf; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndianInput; @Internal class Blob { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + private byte[] _value; Blob() {} void read( LittleEndianInput lei ) { int size = lei.readInt(); - _value = new byte[size]; + _value = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); if ( size > 0 ) { lei.readFully(_value); } diff --git a/src/java/org/apache/poi/hpsf/ClipboardData.java b/src/java/org/apache/poi/hpsf/ClipboardData.java index 3617c4ac6c..ddc8ab0978 100644 --- a/src/java/org/apache/poi/hpsf/ClipboardData.java +++ b/src/java/org/apache/poi/hpsf/ClipboardData.java @@ -26,6 +26,9 @@ import org.apache.poi.util.POILogger; @Internal 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 int _format; @@ -48,7 +51,7 @@ class ClipboardData { } _format = lei.readInt(); - _value = new byte[size - LittleEndianConsts.INT_SIZE]; + _value = IOUtils.safelyAllocate(size - LittleEndianConsts.INT_SIZE, MAX_RECORD_LENGTH); lei.readFully(_value); } diff --git a/src/java/org/apache/poi/hpsf/CodePageString.java b/src/java/org/apache/poi/hpsf/CodePageString.java index d0d138a40b..e45d224cdf 100644 --- a/src/java/org/apache/poi/hpsf/CodePageString.java +++ b/src/java/org/apache/poi/hpsf/CodePageString.java @@ -21,6 +21,7 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import org.apache.poi.util.CodePageUtil; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayInputStream; @@ -30,6 +31,9 @@ import org.apache.poi.util.POILogger; @Internal 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 byte[] _value; @@ -40,7 +44,7 @@ class CodePageString { void read( LittleEndianByteArrayInputStream lei ) { int offset = lei.getReadIndex(); int size = lei.readInt(); - _value = new byte[size]; + _value = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); if (size == 0) { return; } diff --git a/src/java/org/apache/poi/hpsf/Section.java b/src/java/org/apache/poi/hpsf/Section.java index 0669ff34ca..33fc3d4bb1 100644 --- a/src/java/org/apache/poi/hpsf/Section.java +++ b/src/java/org/apache/poi/hpsf/Section.java @@ -33,6 +33,7 @@ import org.apache.commons.collections4.bidimap.TreeBidiMap; import org.apache.poi.hpsf.wellknown.PropertyIDMap; import org.apache.poi.hpsf.wellknown.SectionIDMap; import org.apache.poi.util.CodePageUtil; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianConsts; @@ -43,6 +44,9 @@ import org.apache.poi.util.POILogger; * Represents a section in a {@link PropertySet}. */ 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); /** @@ -835,7 +839,7 @@ public class Section { } try { - byte buf[] = new byte[nrBytes]; + byte buf[] = IOUtils.safelyAllocate(nrBytes, MAX_RECORD_LENGTH); leis.readFully(buf, 0, nrBytes); final String str = CodePageUtil.getStringFromCodePage(buf, 0, nrBytes, cp); diff --git a/src/java/org/apache/poi/hpsf/UnicodeString.java b/src/java/org/apache/poi/hpsf/UnicodeString.java index 0826ced2d7..71e5fb7a08 100644 --- a/src/java/org/apache/poi/hpsf/UnicodeString.java +++ b/src/java/org/apache/poi/hpsf/UnicodeString.java @@ -21,6 +21,7 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import org.apache.poi.util.CodePageUtil; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayInputStream; @@ -32,6 +33,8 @@ import org.apache.poi.util.StringUtil; @Internal class UnicodeString { 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; @@ -40,7 +43,7 @@ class UnicodeString { void read(LittleEndianByteArrayInputStream lei) { final int length = lei.readInt(); 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 // nonzero, this field MUST be a null-terminated array of 16-bit Unicode characters, followed by diff --git a/src/java/org/apache/poi/hpsf/VariantSupport.java b/src/java/org/apache/poi/hpsf/VariantSupport.java index cf5cadb0b8..7d57cbb5a6 100644 --- a/src/java/org/apache/poi/hpsf/VariantSupport.java +++ b/src/java/org/apache/poi/hpsf/VariantSupport.java @@ -25,6 +25,7 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianConsts; @@ -58,6 +59,9 @@ public class VariantSupport extends Variant { 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; /** @@ -172,7 +176,7 @@ public class VariantSupport extends Variant { typedPropertyValue.readValue(lei); } catch ( UnsupportedOperationException exc ) { 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); throw new ReadingNotSupportedException( type, v ); } @@ -248,7 +252,7 @@ public class VariantSupport extends Variant { default: final int unpadded = lei.getReadIndex()-offset; lei.setReadIndex(offset); - final byte[] v = new byte[unpadded]; + final byte[] v = IOUtils.safelyAllocate(unpadded, MAX_RECORD_LENGTH); lei.readFully( v, 0, unpadded ); throw new ReadingNotSupportedException( type, v ); } diff --git a/src/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java b/src/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java index 7b76bca7c0..619984fdc5 100644 --- a/src/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java +++ b/src/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java @@ -57,6 +57,9 @@ import org.apache.poi.util.IOUtils; public class OldExcelExtractor implements Closeable { 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; @@ -278,7 +281,7 @@ public class OldExcelExtractor implements Closeable { break; default: - ris.readFully(new byte[ris.remaining()]); + ris.readFully(IOUtils.safelyAllocate(ris.remaining(), MAX_RECORD_LENGTH)); } } diff --git a/src/java/org/apache/poi/hssf/record/CFRule12Record.java b/src/java/org/apache/poi/hssf/record/CFRule12Record.java index 3ec98c8004..52bcf2ad24 100644 --- a/src/java/org/apache/poi/hssf/record/CFRule12Record.java +++ b/src/java/org/apache/poi/hssf/record/CFRule12Record.java @@ -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.util.CellRangeAddress; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogger; @@ -50,6 +51,10 @@ import org.apache.poi.util.POILogger; * this is only used for the other types */ 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; private FtrHeader futureHeader; @@ -92,7 +97,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl priority = 0; template_type = getConditionType(); 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 { int len = readFormatOptions(in); 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); } } @@ -252,7 +257,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl template_type = in.readUShort(); template_param_length = in.readByte(); 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); } else { 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 // we saw some such files in circulation 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); rec.formula_scale = formula_scale.copy(); @@ -474,7 +479,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl rec.priority = priority; rec.template_type = template_type; 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); if (color_gradient != null) { @@ -487,7 +492,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl rec.data_bar = (DataBarFormatting)data_bar.clone(); } 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); } diff --git a/src/java/org/apache/poi/hssf/record/DConRefRecord.java b/src/java/org/apache/poi/hssf/record/DConRefRecord.java index 23bbdda117..f23f7317e6 100644 --- a/src/java/org/apache/poi/hssf/record/DConRefRecord.java +++ b/src/java/org/apache/poi/hssf/record/DConRefRecord.java @@ -20,6 +20,7 @@ package org.apache.poi.hssf.record; import java.util.Arrays; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; @@ -69,6 +70,9 @@ import org.apache.poi.util.StringUtil; 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, * sid = {@value} @@ -142,7 +146,7 @@ public class DConRefRecord extends StandardRecord */ int byteLength = charCount * ((charType & 1) + 1); - path = LittleEndian.getByteArray(data, offset, byteLength); + path = LittleEndian.getByteArray(data, offset, byteLength, MAX_RECORD_LENGTH); offset += byteLength; /* @@ -150,7 +154,7 @@ public class DConRefRecord extends StandardRecord * unused field. Not sure If i need to bother with this... */ 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. int byteLength = charCount * (charType + 1); - path = new byte[byteLength]; + path = IOUtils.safelyAllocate(byteLength, MAX_RECORD_LENGTH); inStream.readFully(path); if (path[0] == 0x02) diff --git a/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java b/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java index ae27771788..b431223c42 100644 --- a/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java @@ -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.RefPtg; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInputStream; @@ -41,6 +42,9 @@ import org.apache.poi.util.StringUtil; */ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Cloneable { 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; private static final byte[] EMPTY_BYTE_ARRAY = { }; @@ -173,7 +177,7 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone if (size == 0) { return EMPTY_BYTE_ARRAY; } - byte[] result = new byte[size]; + byte[] result = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); in.readFully(result); return result; } diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 10381fb5fd..0eb886c2cc 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -36,6 +36,7 @@ import org.apache.poi.ddf.EscherSerializationListener; import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.RecordFormatException; @@ -85,6 +86,9 @@ import org.apache.poi.util.RecordFormatException; public final class EscherAggregate extends AbstractEscherHolderRecord { public static final short sid = 9876; // not a real sid - dummy value 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_NOT_PRIMATIVE = ST_MIN; @@ -592,7 +596,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { // Determine buffer size List records = getEscherRecords(); int rawEscherSize = getEscherRecordSize(records); - byte[] buffer = new byte[rawEscherSize]; + byte[] buffer = IOUtils.safelyAllocate(rawEscherSize, MAX_RECORD_LENGTH); final List spEndingOffsets = new ArrayList<>(); int pos = 0; for (EscherRecord e : records) { diff --git a/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java b/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java index 28159b757c..76b4a4ee62 100644 --- a/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; @@ -48,7 +49,7 @@ public final class FtCblsSubRecord extends SubRecord implements Cloneable { throw new RecordFormatException("Unexpected size (" + size + ")"); } //just grab the raw data - byte[] buf = new byte[size]; + byte[] buf = IOUtils.safelyAllocate(size, ENCODED_SIZE); in.readFully(buf); reserved = buf; } diff --git a/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java b/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java index c7af79ee33..575ed7a5af 100644 --- a/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; 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 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 = { }; @@ -38,7 +42,7 @@ public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { } public GroupMarkerSubRecord(LittleEndianInput in, int size) { - byte[] buf = new byte[size]; + byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); in.readFully(buf); reserved = buf; } diff --git a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java index 623065e08a..f3999b1bcd 100644 --- a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java +++ b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java @@ -20,6 +20,7 @@ package org.apache.poi.hssf.record; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.HexDump; import org.apache.poi.util.HexRead; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianInput; 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 static short sid = 0x01B8; 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 { /* @@ -525,7 +529,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { int len = in.readInt(); - byte[] path_bytes = new byte[len]; + byte[] path_bytes = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH); in.readFully(path_bytes); _address = new String(path_bytes, StringUtil.UTF8); diff --git a/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java b/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java index e2aa1e0008..4f651b7c55 100644 --- a/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; @@ -55,7 +56,7 @@ public final class NoteStructureSubRecord extends SubRecord implements Cloneable throw new RecordFormatException("Unexpected size (" + size + ")"); } //just grab the raw data - byte[] buf = new byte[size]; + byte[] buf = IOUtils.safelyAllocate(size, ENCODED_SIZE); in.readFully(buf); reserved = buf; } diff --git a/src/java/org/apache/poi/hssf/record/OldLabelRecord.java b/src/java/org/apache/poi/hssf/record/OldLabelRecord.java index d77a45fc80..447291daa3 100644 --- a/src/java/org/apache/poi/hssf/record/OldLabelRecord.java +++ b/src/java/org/apache/poi/hssf/record/OldLabelRecord.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.RecordFormatException; @@ -29,6 +30,8 @@ import org.apache.poi.util.RecordFormatException; */ public final class OldLabelRecord extends OldCellRecord { 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 biff345_sid = 0x0204; @@ -51,7 +54,7 @@ public final class OldLabelRecord extends OldCellRecord { } // 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); if (in.remaining() > 0) { diff --git a/src/java/org/apache/poi/hssf/record/OldSheetRecord.java b/src/java/org/apache/poi/hssf/record/OldSheetRecord.java index 92ffcf923b..8ccb3cf9d3 100644 --- a/src/java/org/apache/poi/hssf/record/OldSheetRecord.java +++ b/src/java/org/apache/poi/hssf/record/OldSheetRecord.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; /** * Title: Bound Sheet Record (aka BundleSheet) (0x0085) for BIFF 5

@@ -26,6 +27,10 @@ import org.apache.poi.util.HexDump; * file. */ 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; private int field_1_position_of_BOF; @@ -39,7 +44,7 @@ public final class OldSheetRecord { field_2_visibility = in.readUByte(); field_3_type = 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); } diff --git a/src/java/org/apache/poi/hssf/record/OldStringRecord.java b/src/java/org/apache/poi/hssf/record/OldStringRecord.java index b28783c897..e99313ee19 100644 --- a/src/java/org/apache/poi/hssf/record/OldStringRecord.java +++ b/src/java/org/apache/poi/hssf/record/OldStringRecord.java @@ -21,6 +21,7 @@ import java.io.UnsupportedEncodingException; import org.apache.poi.hpsf.Property; 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. */ 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 biff345_sid = 0x0207; @@ -49,7 +54,7 @@ public final class OldStringRecord { } // 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); } diff --git a/src/java/org/apache/poi/hssf/record/RecordInputStream.java b/src/java/org/apache/poi/hssf/record/RecordInputStream.java index 11cd63cc03..4f5f589032 100644 --- a/src/java/org/apache/poi/hssf/record/RecordInputStream.java +++ b/src/java/org/apache/poi/hssf/record/RecordInputStream.java @@ -25,6 +25,7 @@ import java.util.Locale; import org.apache.poi.hssf.dev.BiffViewer; import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream; import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndianConsts; 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.

*/ public final class RecordInputStream implements LittleEndianInput { + + /** Maximum size of a single record (minus the 4 byte header) without a continue*/ public final static short MAX_RECORD_DATA_SIZE = 8224; 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 * 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) { return EMPTY_BYTE_ARRAY; } - byte[] result = new byte[size]; + byte[] result = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); readFully(result); return result; } diff --git a/src/java/org/apache/poi/hssf/record/SubRecord.java b/src/java/org/apache/poi/hssf/record/SubRecord.java index 2f74b5996b..9e24213519 100644 --- a/src/java/org/apache/poi/hssf/record/SubRecord.java +++ b/src/java/org/apache/poi/hssf/record/SubRecord.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutputStream; @@ -28,6 +29,10 @@ import java.io.ByteArrayOutputStream; * Subrecords are part of the OBJ class. */ public abstract class SubRecord { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + protected SubRecord() { // no fields to initialise } @@ -107,7 +112,7 @@ public abstract class SubRecord { public UnknownSubRecord(LittleEndianInput in, int sid, int size) { _sid = sid; - byte[] buf = new byte[size]; + byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); in.readFully(buf); _data = buf; } diff --git a/src/java/org/apache/poi/hssf/record/common/UnicodeString.java b/src/java/org/apache/poi/hssf/record/common/UnicodeString.java index 818e65087b..e20b5d5211 100644 --- a/src/java/org/apache/poi/hssf/record/common/UnicodeString.java +++ b/src/java/org/apache/poi/hssf/record/common/UnicodeString.java @@ -28,6 +28,7 @@ import org.apache.poi.hssf.record.cont.ContinuableRecordInput; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; @@ -46,6 +47,10 @@ public class UnicodeString implements Comparable { // TODO - make this final when the compatibility version is removed 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 byte field_2_optionflags; private String field_3_string; @@ -196,7 +201,7 @@ public class UnicodeString implements Comparable { _logger.log( POILogger.WARN, "Warning - ExtRst overran by " + (0-extraDataLength) + " bytes"); extraDataLength = 0; } - extraData = new byte[extraDataLength]; + extraData = IOUtils.safelyAllocate(extraDataLength, MAX_RECORD_LENGTH); for(int i=0; i> chunkBits); this.cipher = initCipherForBlock(null, lastIndex); diff --git a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java index a846cca34f..62835109eb 100644 --- a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java +++ b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java @@ -47,6 +47,9 @@ import org.apache.poi.util.TempFile; @Internal public abstract class ChunkedCipherOutputStream extends FilterOutputStream { 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 final int chunkSize; @@ -70,7 +73,7 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream { super(null); this.chunkSize = 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.chunkBits = Integer.bitCount(cs-1); this.fileOut = TempFile.createTempFile("encrypted_package", "crypt"); @@ -84,7 +87,7 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream { super(stream); this.chunkSize = 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.chunkBits = Integer.bitCount(cs-1); this.fileOut = null; diff --git a/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java b/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java index e305376904..af829839f8 100644 --- a/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java +++ b/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java @@ -34,6 +34,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; @@ -44,6 +45,10 @@ import org.apache.poi.util.StringUtil; */ @Internal public class CryptoFunctions { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + /** *

2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)
* 2.3.4.11 Encryption Key Generation (Agile Encryption)

@@ -280,7 +285,7 @@ public class CryptoFunctions { private static byte[] getBlockX(byte[] hash, int size, byte fill) { if (hash.length == size) return hash; - byte[] result = new byte[size]; + byte[] result = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); Arrays.fill(result, fill); System.arraycopy(hash, 0, result, 0, Math.min(result.length, hash.length)); return result; diff --git a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java index 2f5ccfd7a9..620b168eb0 100644 --- a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java +++ b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java @@ -26,6 +26,7 @@ import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.POIFSWriterEvent; import org.apache.poi.poifs.filesystem.POIFSWriterListener; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianInput; @@ -33,6 +34,10 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; 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 { DataSpaceMapEntry dsme = new DataSpaceMapEntry( new int[]{ 0 } @@ -332,7 +337,7 @@ public class DataSpaceMapUtils { return length == 0 ? null : ""; } - byte data[] = new byte[length]; + byte data[] = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH); 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 diff --git a/src/java/org/apache/poi/poifs/dev/POIFSDump.java b/src/java/org/apache/poi/poifs/dev/POIFSDump.java index ad3e6176ee..60a790e241 100644 --- a/src/java/org/apache/poi/poifs/dev/POIFSDump.java +++ b/src/java/org/apache/poi/poifs/dev/POIFSDump.java @@ -39,6 +39,10 @@ import org.apache.poi.util.IOUtils; * Dump internal structure of a OLE2 file into file system */ 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 { if (args.length == 0) { System.err.println("Must specify at least one file to dump"); @@ -132,7 +136,7 @@ public class POIFSDump { try { 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) { int len = bb.remaining(); bb.get(b); diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java index c77ce9e046..314cae0ee2 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java @@ -20,6 +20,7 @@ package org.apache.poi.poifs.filesystem; import java.io.IOException; import java.io.InputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.SuppressForbidden; diff --git a/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java index 848fd9f006..b32166ac1c 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java @@ -22,6 +22,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; import org.apache.poi.poifs.property.DocumentProperty; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -224,7 +225,7 @@ public final class NDocumentInputStream extends DocumentInputStream { long rval = new_offset - _current_offset; // TODO Do this better - byte[] skip = new byte[(int)rval]; + byte[] skip = IOUtils.safelyAllocate(rval, Integer.MAX_VALUE); readFully(skip); return rval; } diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java index 7e7ca0780c..22e4106962 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java @@ -31,13 +31,18 @@ import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.dev.POIFSViewable; import org.apache.poi.poifs.property.DocumentProperty; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; /** * This class manages a document in the NIO POIFS filesystem. * This is the {@link NPOIFSFileSystem} version. */ 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 NPOIFSStream _stream; @@ -147,7 +152,7 @@ public final class NPOIFSDocument implements POIFSViewable { int usedInBlock = length % _block_size; if (usedInBlock != 0 && usedInBlock != _block_size) { int toBlockEnd = _block_size - usedInBlock; - byte[] padding = new byte[toBlockEnd]; + byte[] padding = IOUtils.safelyAllocate(toBlockEnd, MAX_RECORD_LENGTH); Arrays.fill(padding, (byte)0xFF); os.write(padding); } @@ -214,7 +219,7 @@ public final class NPOIFSDocument implements POIFSViewable { if(getSize() > 0) { // Get all the data into a single array - byte[] data = new byte[getSize()]; + byte[] data = IOUtils.safelyAllocate(getSize(), MAX_RECORD_LENGTH); int offset = 0; for(ByteBuffer buffer : _stream) { int length = Math.min(_block_size, data.length-offset); diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java index b3d9d4c8f8..62a132ee45 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java @@ -66,7 +66,10 @@ import org.apache.poi.util.POILogger; public class NPOIFSFileSystem extends BlockStore 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. @@ -103,7 +106,8 @@ public class NPOIFSFileSystem extends BlockStore if(newFS) { // Data needs to initially hold just the header block, // 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)); } } diff --git a/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java b/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java index 5d197a8002..7c1b9bec16 100644 --- a/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java +++ b/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java @@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianOutputStream; @@ -34,9 +35,12 @@ import org.apache.poi.util.StringUtil; */ public class Ole10Native { + public static final String OLE10_NATIVE = "\u0001Ole10Native"; 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:) private int totalSize; // 4 bytes, total size of record not including this field 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 { DocumentEntry nativeEntry = (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); assert(readBytes == data.length); @@ -196,7 +200,7 @@ public class Ole10Native { if ((long)dataSize + (long)ofs > (long)data.length) { //cast to avoid overflow 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); ofs += dataSize; } diff --git a/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java b/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java index 88ee7da7f3..72758c2d97 100644 --- a/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java +++ b/src/java/org/apache/poi/poifs/nio/ByteArrayBackedDataSource.java @@ -17,6 +17,8 @@ package org.apache.poi.poifs.nio; +import org.apache.poi.util.IOUtils; + import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; @@ -25,6 +27,9 @@ import java.nio.ByteBuffer; * A POIFS {@link DataSource} backed by a byte array. */ public class ByteArrayBackedDataSource extends DataSource { + //Can we make this shorter? + private static final int MAX_RECORD_LENGTH = Integer.MAX_VALUE; + private byte[] buffer; private long size; @@ -76,7 +81,8 @@ public class ByteArrayBackedDataSource extends DataSource { 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); buffer = nb; } diff --git a/src/java/org/apache/poi/poifs/property/NPropertyTable.java b/src/java/org/apache/poi/poifs/property/NPropertyTable.java index fe948baf2c..d155f0079d 100644 --- a/src/java/org/apache/poi/poifs/property/NPropertyTable.java +++ b/src/java/org/apache/poi/poifs/property/NPropertyTable.java @@ -29,6 +29,7 @@ import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSStream; import org.apache.poi.poifs.storage.HeaderBlock; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -40,6 +41,9 @@ import org.apache.poi.util.POILogger; public final class NPropertyTable extends PropertyTableBase { private static final POILogger _logger = POILogFactory.getLogger(NPropertyTable.class); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private POIFSBigBlockSize _bigBigBlockSize; public NPropertyTable(HeaderBlock headerBlock) @@ -86,7 +90,7 @@ public final class NPropertyTable extends PropertyTableBase { bb.array().length == bigBlockSize.getBigBlockSize()) { data = bb.array(); } else { - data = new byte[bigBlockSize.getBigBlockSize()]; + data = IOUtils.safelyAllocate(bigBlockSize.getBigBlockSize(), MAX_RECORD_LENGTH); int toRead = data.length; if (bb.remaining() < bigBlockSize.getBigBlockSize()) { diff --git a/src/java/org/apache/poi/poifs/storage/DocumentBlock.java b/src/java/org/apache/poi/poifs/storage/DocumentBlock.java index a7c5686257..3d9c67c652 100644 --- a/src/java/org/apache/poi/poifs/storage/DocumentBlock.java +++ b/src/java/org/apache/poi/poifs/storage/DocumentBlock.java @@ -32,6 +32,10 @@ import org.apache.poi.util.IOUtils; * @author Marc Johnson (mjohnson at apache dot org) */ 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 byte[] _data; private int _bytes_read; @@ -81,7 +85,7 @@ public final class DocumentBlock extends BigBlock { private DocumentBlock(POIFSBigBlockSize bigBlockSize) { super(bigBlockSize); - _data = new byte[ bigBlockSize.getBigBlockSize() ]; + _data = IOUtils.safelyAllocate(bigBlockSize.getBigBlockSize(), MAX_RECORD_LENGTH); Arrays.fill(_data, _default_value); } diff --git a/src/java/org/apache/poi/poifs/storage/HeaderBlock.java b/src/java/org/apache/poi/poifs/storage/HeaderBlock.java index 5319a2173f..c833138a24 100644 --- a/src/java/org/apache/poi/poifs/storage/HeaderBlock.java +++ b/src/java/org/apache/poi/poifs/storage/HeaderBlock.java @@ -41,7 +41,11 @@ import org.apache.poi.util.ShortField; * The block containing the archive header */ 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 @@ -104,7 +108,7 @@ public final class HeaderBlock implements HeaderBlockConstants { // Fetch the rest of the block if needed if(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); } } diff --git a/src/java/org/apache/poi/poifs/storage/RawDataBlock.java b/src/java/org/apache/poi/poifs/storage/RawDataBlock.java index 923e76fac8..6ed834617d 100644 --- a/src/java/org/apache/poi/poifs/storage/RawDataBlock.java +++ b/src/java/org/apache/poi/poifs/storage/RawDataBlock.java @@ -35,6 +35,9 @@ import java.io.*; public class RawDataBlock implements ListManagedBlock { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private byte[] _data; private boolean _eof; private boolean _hasData; @@ -66,7 +69,7 @@ public class RawDataBlock */ public RawDataBlock(final InputStream stream, int blockSize) throws IOException { - _data = new byte[ blockSize ]; + _data = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH); int count = IOUtils.readFully(stream, _data); _hasData = (count > 0); diff --git a/src/java/org/apache/poi/ss/formula/Formula.java b/src/java/org/apache/poi/ss/formula/Formula.java index 745a482d2d..b0a2842040 100644 --- a/src/java/org/apache/poi/ss/formula/Formula.java +++ b/src/java/org/apache/poi/ss/formula/Formula.java @@ -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.TblPtg; import org.apache.poi.ss.util.CellReference; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianInput; @@ -35,6 +36,9 @@ import org.apache.poi.util.LittleEndianOutput; */ 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); /** immutable */ @@ -72,7 +76,7 @@ public class Formula { * @return A new formula object as read from the stream. Possibly empty, never null. */ 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); return new Formula(byteEncoding, encodedTokenLen); } diff --git a/src/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java b/src/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java index 29b9612aec..e23275dbe3 100644 --- a/src/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java +++ b/src/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java @@ -28,6 +28,7 @@ import java.util.Set; import java.util.regex.Pattern; import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.util.IOUtils; /** * Converts the text meta-data file into a FunctionMetadataRegistry @@ -36,6 +37,9 @@ import org.apache.poi.ss.formula.ptg.Ptg; */ 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"; /** 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) nItems --; } - byte[] result = new byte[nItems]; + byte[] result = IOUtils.safelyAllocate(nItems, MAX_RECORD_LENGTH); for (int i = 0; i < nItems; i++) { result[i] = parseOperandTypeCode(array[i]); } diff --git a/src/java/org/apache/poi/util/IOUtils.java b/src/java/org/apache/poi/util/IOUtils.java index be63655a4b..c09ddf4e13 100644 --- a/src/java/org/apache/poi/util/IOUtils.java +++ b/src/java/org/apache/poi/util/IOUtils.java @@ -34,12 +34,26 @@ public final class IOUtils { * The default buffer size to use for the skip() methods. */ private static final int SKIP_BUFFER_SIZE = 2048; + private static int BYTE_ARRAY_MAX_OVERRIDE = -1; private static byte[] SKIP_BYTE_BUFFER; private IOUtils() { // 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 * 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) { throw new RecordFormatException("Can't allocate an array > "+Integer.MAX_VALUE); } - if (length > maxLength) { - throw new RecordFormatException("Not allowed to allocate an array > "+ - maxLength+" for this record type." + - "If the file is not corrupt, please open an issue on bugzilla to request " + - "increasing the maximum allowable size for this record type"); + if (BYTE_ARRAY_MAX_OVERRIDE > 0) { + if (length > BYTE_ARRAY_MAX_OVERRIDE) { + throwRFE(length, BYTE_ARRAY_MAX_OVERRIDE); + } + } else if (length > maxLength) { + throwRFE(length, maxLength); } 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()"); + + } } diff --git a/src/java/org/apache/poi/util/LZWDecompresser.java b/src/java/org/apache/poi/util/LZWDecompresser.java index 91aeb23b91..ab24bf0f25 100644 --- a/src/java/org/apache/poi/util/LZWDecompresser.java +++ b/src/java/org/apache/poi/util/LZWDecompresser.java @@ -32,6 +32,10 @@ import java.io.OutputStream; * http://marknelson.us/1989/10/01/lzw-data-compression/ */ 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? */ @@ -119,7 +123,7 @@ public abstract class LZWDecompresser { // These are bytes as looked up in the dictionary // It needs to be signed, as it'll get passed on to // 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 // It needs to be unsigned, so that bit stuff works int dataI; diff --git a/src/java/org/apache/poi/util/LittleEndian.java b/src/java/org/apache/poi/util/LittleEndian.java index 1293e46ee6..2bd1b3ab16 100644 --- a/src/java/org/apache/poi/util/LittleEndian.java +++ b/src/java/org/apache/poi/util/LittleEndian.java @@ -63,6 +63,9 @@ public class LittleEndian implements LittleEndianConsts * @param size * Number of bytes to copy. * @return The byteArray value + * + * @see #getByteArray(byte[], int, int, long) if size is not a constant + * * @throws IndexOutOfBoundsException * - if copying would cause access of data outside array bounds. */ @@ -74,6 +77,31 @@ public class LittleEndian implements LittleEndianConsts 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 * then converts the resulting revolting IEEE 754 (curse them) floating diff --git a/src/java/org/apache/poi/util/StringUtil.java b/src/java/org/apache/poi/util/StringUtil.java index e0473b2b5a..b9b904d669 100644 --- a/src/java/org/apache/poi/util/StringUtil.java +++ b/src/java/org/apache/poi/util/StringUtil.java @@ -28,6 +28,9 @@ import java.util.Map; @Internal public class StringUtil { 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 UTF8 = Charset.forName("UTF-8"); public static final Charset WIN_1252 = Charset.forName("cp1252"); @@ -118,7 +121,7 @@ public class StringUtil { } public static String readCompressedUnicode(LittleEndianInput in, int nChars) { - byte[] buf = new byte[nChars]; + byte[] buf = IOUtils.safelyAllocate(nChars, MAX_RECORD_LENGTH); in.readFully(buf); return new String(buf, ISO_8859_1); } @@ -252,7 +255,7 @@ public class StringUtil { } 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); return new String(bytes, UTF16LE); } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java index 407831a663..3ff47e3e8a 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java @@ -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.standard.EncryptionRecord; import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayOutputStream; 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; 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 pwHash[]; @@ -91,11 +96,11 @@ public class AgileEncryptor extends Encryptor implements Cloneable { int keySize = header.getKeySize()/8; int hashSize = header.getHashAlgorithm().hashSize; - byte[] newVerifierSalt = new byte[blockSize] - , newVerifier = new byte[blockSize] - , newKeySalt = new byte[blockSize] - , newKeySpec = new byte[keySize] - , newIntegritySalt = new byte[hashSize]; + byte[] newVerifierSalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH) + , newVerifier = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH) + , newKeySalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH) + , newKeySpec = IOUtils.safelyAllocate(keySize, MAX_RECORD_LENGTH) + , newIntegritySalt = IOUtils.safelyAllocate(hashSize, MAX_RECORD_LENGTH); r.nextBytes(newVerifierSalt); // blocksize r.nextBytes(newVerifier); // blocksize r.nextBytes(newKeySalt); // blocksize diff --git a/src/ooxml/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java b/src/ooxml/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java index 2fa5fc21d7..5c235267ca 100644 --- a/src/ooxml/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java +++ b/src/ooxml/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java @@ -57,7 +57,9 @@ import org.apache.poi.xssf.usermodel.XSSFObjectData; @Beta public class EmbeddedExtractor implements Iterable { 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 private static final String CONTENT_TYPE_BYTES = "binary/octet-stream"; private static final String CONTENT_TYPE_PDF = "application/pdf"; @@ -252,7 +254,7 @@ public class EmbeddedExtractor implements Iterable { } 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); String filename = source.getShapeName().trim(); if (!endsWithIgnoreCase(filename, ".pdf")) { diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index 8f13332af2..8f5dd8f84e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -73,6 +73,8 @@ import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument public class XMLSlideShow extends POIXMLDocument implements SlideShow { 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 List _slides; @@ -533,7 +535,7 @@ implements SlideShow { public XSLFPictureData addPicture(File pict, PictureType format) throws IOException { int length = (int) pict.length(); - byte[] data = new byte[length]; + byte[] data = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH); FileInputStream is = new FileInputStream(pict); try { IOUtils.readFully(is, data); diff --git a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java index 3c52ed78ca..ac24ecd909 100644 --- a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java +++ b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.BitSet; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndianInputStream; @@ -34,6 +35,9 @@ import org.apache.poi.util.LittleEndianInputStream; @Internal 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 BitSet records; @@ -88,8 +92,7 @@ public abstract class XSSFBParser { } if (records == null || records.get(recordId)) { - //add sanity check for length? - byte[] buff = new byte[(int) recordLength]; + byte[] buff = IOUtils.safelyAllocate(recordLength, MAX_RECORD_LENGTH); is.readFully(buff); handleRecord(recordId, buff); } else { diff --git a/src/scratchpad/src/org/apache/poi/hdgf/chunks/ChunkFactory.java b/src/scratchpad/src/org/apache/poi/hdgf/chunks/ChunkFactory.java index 762c2a12a9..b83979e145 100644 --- a/src/scratchpad/src/org/apache/poi/hdgf/chunks/ChunkFactory.java +++ b/src/scratchpad/src/org/apache/poi/hdgf/chunks/ChunkFactory.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -38,6 +39,11 @@ import org.apache.poi.util.POILogger; * to process the chunk value area */ 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 */ private int version; /** @@ -179,7 +185,7 @@ public final class ChunkFactory { } // 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); Chunk chunk = new Chunk(header, trailer, separator, contents); diff --git a/src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java b/src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java index 24ba19653a..953987e7b4 100644 --- a/src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java +++ b/src/scratchpad/src/org/apache/poi/hdgf/streams/CompressedStreamStore.java @@ -21,12 +21,17 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.poi.hdgf.HDGFLZW; +import org.apache.poi.util.IOUtils; /** * A StreamStore where the data on-disk is compressed, * using the crazy Visio LZW */ 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 */ private byte[] compressedContents; /** @@ -46,7 +51,7 @@ public final class CompressedStreamStore extends StreamStore { protected CompressedStreamStore(byte[] data, int offset, int length) throws IOException { this(decompress(data,offset,length)); - compressedContents = new byte[length]; + compressedContents = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH); System.arraycopy(data, offset, compressedContents, 0, length); } /** diff --git a/src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java b/src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java index 1c4e4e7ed8..30dead90a3 100644 --- a/src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java +++ b/src/scratchpad/src/org/apache/poi/hdgf/streams/StreamStore.java @@ -17,24 +17,29 @@ package org.apache.poi.hdgf.streams; +import org.apache.poi.util.IOUtils; + /** * Holds the representation of the stream on-disk, and * handles de-compressing it as required. * In future, may also handle writing it back out again */ 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; /** * Creates a new, non compressed Stream Store */ 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); } 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(contents, 0, newContents, b.length, contents.length); contents = newContents; diff --git a/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentEMFPlus.java b/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentEMFPlus.java index 873d42e1ee..d5d4c10e84 100644 --- a/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentEMFPlus.java +++ b/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentEMFPlus.java @@ -34,7 +34,7 @@ import org.apache.poi.util.RecordFormatException; @Internal 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; diff --git a/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentPublic.java b/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentPublic.java index d527ed1c1b..5ca5c375ce 100644 --- a/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentPublic.java +++ b/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentPublic.java @@ -36,7 +36,7 @@ import org.apache.poi.util.RecordFormatException; @Internal public class HemfCommentPublic { - private static final int MAX_RECORD_LENGTH = 1000000; + private static final int MAX_RECORD_LENGTH = 1_000_000; /** diff --git a/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentRecord.java b/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentRecord.java index 90510f8d8f..af8aa28572 100644 --- a/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentRecord.java +++ b/src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentRecord.java @@ -36,7 +36,7 @@ import org.apache.poi.util.RecordFormatException; */ @Internal 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_EMFPLUS = 0x2B464D45; diff --git a/src/scratchpad/src/org/apache/poi/hemf/record/HemfHeader.java b/src/scratchpad/src/org/apache/poi/hemf/record/HemfHeader.java index 2c3694c844..7a6f876400 100644 --- a/src/scratchpad/src/org/apache/poi/hemf/record/HemfHeader.java +++ b/src/scratchpad/src/org/apache/poi/hemf/record/HemfHeader.java @@ -32,7 +32,7 @@ import org.apache.poi.util.LittleEndianInputStream; @Internal 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; diff --git a/src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java b/src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java index 8c32812d7f..87a7b46988 100644 --- a/src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java +++ b/src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java @@ -40,7 +40,7 @@ import org.apache.poi.util.RecordFormatException; public class HemfText { 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 { } diff --git a/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIAttribute.java b/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIAttribute.java index bb077b8f5b..159328fe70 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIAttribute.java +++ b/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIAttribute.java @@ -38,6 +38,10 @@ import org.apache.poi.util.StringUtil; * or one of its {@link Attachment}s. */ 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 int type; private final byte[] data; @@ -144,7 +148,7 @@ public class MAPIAttribute { } else { // Custom name was stored int mplen = LittleEndian.readInt(inp); - byte[] mpdata = new byte[mplen]; + byte[] mpdata = IOUtils.safelyAllocate(mplen, MAX_RECORD_LENGTH); IOUtils.readFully(inp, mpdata); name = StringUtil.getFromUnicodeLE(mpdata, 0, (mplen/2)-1); skipToBoundary(mplen, inp); @@ -164,7 +168,7 @@ public class MAPIAttribute { } for(int j=0; j 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); } else { this.decompressed = tmp; diff --git a/src/scratchpad/src/org/apache/poi/hmef/attribute/TNEFAttribute.java b/src/scratchpad/src/org/apache/poi/hmef/attribute/TNEFAttribute.java index 8e386ca994..11e865364d 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/attribute/TNEFAttribute.java +++ b/src/scratchpad/src/org/apache/poi/hmef/attribute/TNEFAttribute.java @@ -33,6 +33,10 @@ import org.apache.poi.util.LittleEndian; * ones, so we can't just re-use the HSMF ones. */ 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 int type; private final byte[] data; @@ -47,7 +51,7 @@ public class TNEFAttribute { int length = LittleEndian.readInt(inp); property = TNEFProperty.getBest(id, type); - data = new byte[length]; + data = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH); IOUtils.readFully(inp, data); checksum = LittleEndian.readUShort(inp); diff --git a/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java b/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java index fd79b290cd..edf9649743 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java +++ b/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java @@ -29,12 +29,17 @@ import org.apache.poi.hmef.attribute.TNEFDateAttribute; import org.apache.poi.hmef.attribute.TNEFProperty; import org.apache.poi.hmef.attribute.TNEFStringAttribute; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** * Developer focused raw dumper */ 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 { if(args.length < 1) { throw new IllegalArgumentException("Filename must be given"); @@ -138,7 +143,7 @@ public final class HMEFDumper { 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.out.print( diff --git a/src/scratchpad/src/org/apache/poi/hpbf/model/EscherPart.java b/src/scratchpad/src/org/apache/poi/hpbf/model/EscherPart.java index 94b7536d88..32ff69f24a 100644 --- a/src/scratchpad/src/org/apache/poi/hpbf/model/EscherPart.java +++ b/src/scratchpad/src/org/apache/poi/hpbf/model/EscherPart.java @@ -23,11 +23,16 @@ import java.util.ArrayList; import org.apache.poi.ddf.DefaultEscherRecordFactory; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.util.IOUtils; /** * Parent class of all Escher parts */ 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; /** @@ -69,7 +74,7 @@ public abstract class EscherPart extends HPBFPart { size += records[i].getRecordSize(); } - byte data[] = new byte[size]; + byte data[] = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); size = 0; for(int i=0; i= start+len) { - byte[] textBytes = new byte[len]; + byte[] textBytes = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH); System.arraycopy(_contents,start,textBytes,0,len); lastEditUser = StringUtil.getFromUnicodeLE(textBytes); } else { // 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); lastEditUser = StringUtil.getFromCompressedUnicode(textBytes,0,(int)usernameLen); } @@ -219,7 +222,7 @@ public class CurrentUserAtom // 4 = revision // 3 * len = ascii + unicode 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 System.arraycopy(atomHeader,0,_contents,0,4); @@ -238,7 +241,7 @@ public class CurrentUserAtom // The username gets stored twice, once as US // 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); // 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); // 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); System.arraycopy(ucUN,0,_contents,28+asciiUN.length+4,ucUN.length); diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/DocumentAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/DocumentAtom.java index 22a9b7c3ef..e2c49a9f35 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/DocumentAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/DocumentAtom.java @@ -17,6 +17,7 @@ package org.apache.poi.hslf.record; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import java.io.IOException; import java.io.OutputStream; @@ -30,6 +31,9 @@ import java.io.OutputStream; 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 static long _type = 1001l; @@ -137,7 +141,7 @@ public final class DocumentAtom extends RecordAtom showComments = source[start+39+8]; // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java index 94aba471de..5ebb2a43c6 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExEmbedAtom.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -40,6 +41,9 @@ import org.apache.poi.util.LittleEndian; */ 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. */ @@ -91,7 +95,7 @@ public class ExEmbedAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); // Must be at least 8 bytes long diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlinkAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlinkAtom.java index 99deafdbf2..648f2aaa57 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlinkAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlinkAtom.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -29,6 +30,10 @@ import org.apache.poi.util.LittleEndian; * @author Nick Burch */ public final class ExHyperlinkAtom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + /** * Record header. */ @@ -66,7 +71,7 @@ public final class ExHyperlinkAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); // Must be at least 4 bytes long diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExMediaAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExMediaAtom.java index 058f27ea5c..1ed5829532 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/ExMediaAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExMediaAtom.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -29,6 +30,8 @@ import org.apache.poi.util.LittleEndian; */ 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. @@ -78,7 +81,7 @@ public final class ExMediaAtom extends RecordAtom System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExObjListAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExObjListAtom.java index 51bb5b4ee1..e1224ef0bc 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/ExObjListAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExObjListAtom.java @@ -21,6 +21,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -31,6 +32,10 @@ import org.apache.poi.util.LittleEndian; public class ExObjListAtom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + /** * Record header. */ @@ -68,7 +73,7 @@ public class ExObjListAtom extends RecordAtom System.arraycopy(source,start,_header,0,8); // 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); // Must be at least 4 bytes long diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java index 9f412d249e..7b5a52e2c3 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjAtom.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -65,6 +66,9 @@ import org.apache.poi.util.LittleEndian; */ 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, */ @@ -148,7 +152,7 @@ public class ExOleObjAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); // Must be at least 24 bytes long diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java index 0ba89d7231..6325fe8ec8 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java @@ -27,6 +27,7 @@ import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; import org.apache.poi.util.BoundedInputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -34,6 +35,9 @@ import org.apache.poi.util.LittleEndian; */ 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 /** @@ -72,7 +76,7 @@ public class ExOleObjStg extends PositionDependentRecordAtom implements PersistR System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java index c0be885078..073ce26946 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java @@ -22,6 +22,7 @@ import java.io.OutputStream; import java.util.Arrays; import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; @@ -35,7 +36,11 @@ import org.apache.poi.util.StringUtil; */ public final class FontEntityAtom extends RecordAtom { - /** + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + /** * record header */ private byte[] _header; @@ -54,7 +59,7 @@ public final class FontEntityAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java index 2f82245258..6bcfd2a9a3 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java @@ -27,6 +27,7 @@ import org.apache.poi.ddf.EscherClientDataRecord; import org.apache.poi.ddf.EscherRecordFactory; import org.apache.poi.ddf.EscherSerializationListener; import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -38,6 +39,9 @@ import org.apache.poi.util.LittleEndian; */ public class HSLFEscherClientDataRecord extends EscherClientDataRecord { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + private final List _childRecords = new ArrayList<>(); public List getHSLFChildRecords() { @@ -60,7 +64,7 @@ public class HSLFEscherClientDataRecord extends EscherClientDataRecord { @Override public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { 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); setRemainingData(remainingData); return bytesRemaining + 8; diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/HeadersFootersAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/HeadersFootersAtom.java index b9006051dd..9e9140578e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/HeadersFootersAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/HeadersFootersAtom.java @@ -17,6 +17,7 @@ package org.apache.poi.hslf.record; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import java.io.IOException; import java.io.OutputStream; @@ -30,6 +31,10 @@ import java.io.OutputStream; 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. * @see #getMask() @@ -96,7 +101,7 @@ public final class HeadersFootersAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java index 6dd8fccf6b..15dc05b50d 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -31,6 +32,10 @@ import org.apache.poi.util.LittleEndian; */ public class InteractiveInfoAtom extends RecordAtom { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + + /** * Action Table */ @@ -105,7 +110,7 @@ public class InteractiveInfoAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); // Must be at least 16 bytes long diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/MasterTextPropAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/MasterTextPropAtom.java index 7aef5fcdcc..ba27d73d84 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/MasterTextPropAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/MasterTextPropAtom.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.List; 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.POILogger; @@ -31,6 +32,10 @@ import org.apache.poi.util.POILogger; * Specifies the Indent Level for the text */ public final class MasterTextPropAtom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + /** * Record header. */ @@ -71,7 +76,7 @@ public final class MasterTextPropAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); try { @@ -108,7 +113,7 @@ public final class MasterTextPropAtom extends RecordAtom { */ private void write() { int pos = 0; - _data = new byte[indents.size()*6]; + _data = IOUtils.safelyAllocate(indents.size()*6, MAX_RECORD_LENGTH); for (IndentProp prop : indents) { LittleEndian.putInt(_data, pos, prop.getCharactersCovered()); LittleEndian.putShort(_data, pos+4, (short)prop.getIndentLevel()); diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/NotesAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/NotesAtom.java index 7aace80632..c4e284098b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/NotesAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/NotesAtom.java @@ -17,6 +17,7 @@ package org.apache.poi.hslf.record; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import java.io.IOException; import java.io.OutputStream; @@ -30,6 +31,10 @@ import java.io.OutputStream; 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 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 - reserved = new byte[len-14]; + reserved = IOUtils.safelyAllocate(len-14, MAX_RECORD_LENGTH); System.arraycopy(source,start+14,reserved,0,reserved.length); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java index 6587a6e9d3..fb3d246897 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java @@ -36,6 +36,7 @@ import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; 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 // would require a wrapping class 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 long _type; @@ -100,7 +106,7 @@ public final class PPDrawing extends RecordAtom { _type = LittleEndian.getUShort(_header,2); // 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); // Build up a tree of Escher records contained within diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java index d655e5a4fe..19a536e3cd 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java @@ -18,6 +18,7 @@ package org.apache.poi.hslf.record; import org.apache.poi.ddf.*; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import java.io.OutputStream; @@ -35,6 +36,10 @@ import java.util.Iterator; */ 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 EscherContainerRecord dggContainer; //cached dgg @@ -46,7 +51,7 @@ public final class PPDrawingGroup extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/PersistPtrHolder.java b/src/scratchpad/src/org/apache/poi/hslf/record/PersistPtrHolder.java index 9f018d3c90..22c5b2ad1f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/PersistPtrHolder.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/PersistPtrHolder.java @@ -29,6 +29,7 @@ import java.util.TreeMap; import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.util.BitField; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogger; @@ -46,6 +47,10 @@ import org.apache.poi.util.POILogger; 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 byte[] _ptrData; // Will need to update this once we allow updates to _slideLocations private long _type; @@ -109,7 +114,7 @@ public final class PersistPtrHolder extends PositionDependentRecordAtom // count * 32 bit offsets // Repeat as many times as you have data _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); int pos = 0; diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/SlideAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/SlideAtom.java index 9d553740bf..5d9b347bce 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/SlideAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/SlideAtom.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType; +import org.apache.poi.util.IOUtils; 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; // 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 int masterID; @@ -109,7 +113,7 @@ public final class SlideAtom extends RecordAtom { // If there's any other bits of data, keep them about // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/SlidePersistAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/SlidePersistAtom.java index 0ac22adf34..7c4907f939 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/SlidePersistAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/SlidePersistAtom.java @@ -17,6 +17,7 @@ package org.apache.poi.hslf.record; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import java.io.IOException; import java.io.OutputStream; @@ -28,6 +29,10 @@ import java.io.OutputStream; * @author Nick Burch */ public final class SlidePersistAtom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 32; + private byte[] _header; 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, // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/SoundData.java b/src/scratchpad/src/org/apache/poi/hslf/record/SoundData.java index 32aa9592d3..b29f810c1c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/SoundData.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/SoundData.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -29,6 +30,10 @@ import org.apache.poi.util.LittleEndian; */ public final class SoundData extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + /** * Record header. */ @@ -64,7 +69,7 @@ public final class SoundData extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java b/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java index ea60240518..3f1ec4b18a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java @@ -23,12 +23,17 @@ import java.util.LinkedList; import java.util.List; import org.apache.poi.hslf.model.textproperties.TextPFException9; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** * The atom record that specifies additional text formatting. */ public final class StyleTextProp9Atom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private final TextPFException9[] autoNumberSchemes; /** Record header. */ private byte[] header; @@ -56,7 +61,7 @@ public final class StyleTextProp9Atom extends RecordAtom { this.length = LittleEndian.getInt(header, 4); // 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); for (int i = 0; i < data.length; ) { final TextPFException9 item = new TextPFException9(data, i); diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java index d81b7beca1..0c1fc32e0e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java @@ -27,6 +27,7 @@ import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.model.textproperties.TextPropCollection; import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogger; @@ -46,6 +47,9 @@ import org.apache.poi.util.POILogger; public final class StyleTextPropAtom extends RecordAtom { public static final long _type = RecordTypes.StyleTextPropAtom.typeID; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + private byte[] _header; private byte[] reserved; @@ -132,7 +136,7 @@ public final class StyleTextPropAtom extends RecordAtom { // Save the contents of the atom, until we're asked to go and // decode them (via a call to setParentTextSize(int) - rawContents = new byte[len-8]; + rawContents = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH); System.arraycopy(source,start+8,rawContents,0,rawContents.length); reserved = new byte[0]; @@ -286,7 +290,7 @@ public final class StyleTextPropAtom extends RecordAtom { // Handle anything left over if(pos < rawContents.length) { - reserved = new byte[rawContents.length-pos]; + reserved = IOUtils.safelyAllocate(rawContents.length-pos, rawContents.length); System.arraycopy(rawContents,pos,reserved,0,reserved.length); } @@ -395,7 +399,7 @@ public final class StyleTextPropAtom extends RecordAtom { out.append(" original byte stream \n"); - byte buf[] = new byte[rawContents.length+reserved.length]; + byte buf[] = IOUtils.safelyAllocate(rawContents.length+reserved.length, MAX_RECORD_LENGTH); System.arraycopy(rawContents, 0, buf, 0, rawContents.length); System.arraycopy(reserved, 0, buf, rawContents.length, reserved.length); out.append( HexDump.dump(buf, 0, 0) ); diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TextBytesAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TextBytesAtom.java index 0badc3e31d..5e9eeea795 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TextBytesAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TextBytesAtom.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; @@ -33,6 +34,9 @@ import org.apache.poi.util.StringUtil; public final class TextBytesAtom extends RecordAtom { public static final long _type = RecordTypes.TextBytesAtom.typeID; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + private byte[] _header; /** The bytes that make up the text */ @@ -66,7 +70,7 @@ public final class TextBytesAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TextCharsAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TextCharsAtom.java index fa8ff836d1..570506b719 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TextCharsAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TextCharsAtom.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; @@ -31,6 +32,9 @@ import org.apache.poi.util.StringUtil; public final class TextCharsAtom extends RecordAtom { public static final long _type = RecordTypes.TextCharsAtom.typeID; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + private byte[] _header; /** The bytes that make up the text */ @@ -44,7 +48,7 @@ public final class TextCharsAtom extends RecordAtom { /** Updates the text in the Atom. */ public void setText(String text) { // Convert to little endian unicode - _text = new byte[text.length()*2]; + _text = IOUtils.safelyAllocate(text.length()*2, MAX_RECORD_LENGTH); StringUtil.putUnicodeLE(text,_text,0); // Update the size (header bytes 5-8) @@ -65,7 +69,7 @@ public final class TextCharsAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TextRulerAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TextRulerAtom.java index 7a9ffbeb80..53666d9184 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TextRulerAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TextRulerAtom.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogger; @@ -27,6 +28,10 @@ import org.apache.poi.util.POILogger; * Ruler of a text as it differs from the style's ruler settings. */ public final class TextRulerAtom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + /** * Record header. */ @@ -69,7 +74,7 @@ public final class TextRulerAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); try { diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoAtom.java index dd7076605e..db3eb5ab7a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoAtom.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayInputStream; @@ -34,6 +35,10 @@ import org.apache.poi.util.LittleEndianByteArrayInputStream; * @author Yegor Kozlov */ public final class TextSpecInfoAtom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private static final long _type = RecordTypes.TextSpecInfoAtom.typeID; /** @@ -69,7 +74,7 @@ public final class TextSpecInfoAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java index 7ab311ecf2..0a13d32df8 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java @@ -23,6 +23,10 @@ import java.io.OutputStream; import org.apache.poi.util.*; public class TextSpecInfoRun { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + /** * A enum that specifies the spelling status of a run of text. */ @@ -153,7 +157,7 @@ public class TextSpecInfoRun { if (smartTagFld.isSet(mask)) { // An unsigned integer specifies the count of items in rgSmartTagIndex. int count = source.readInt(); - smartTagsBytes = new byte[4+count*4]; + smartTagsBytes = IOUtils.safelyAllocate(4+count*4, MAX_RECORD_LENGTH); LittleEndian.putInt(smartTagsBytes, 0, count); // An array of SmartTagIndex that specifies the indices. // The count of items in the array is specified by count. diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java index eb9dd8e0ca..66ec91b566 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java @@ -17,6 +17,7 @@ package org.apache.poi.hslf.record; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import java.io.OutputStream; @@ -28,6 +29,10 @@ import java.io.IOException; * @author Yegor Kozlov */ public final class TxInteractiveInfoAtom extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + /** * Record header. */ @@ -63,7 +68,7 @@ public final class TxInteractiveInfoAtom extends RecordAtom { System.arraycopy(source,start,_header,0,8); // 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); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java index 5c9785f21c..70b3221df6 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java @@ -26,6 +26,7 @@ import java.util.List; import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.model.textproperties.TextPropCollection; import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianOutputStream; import org.apache.poi.util.POILogFactory; @@ -49,6 +50,8 @@ import org.apache.poi.util.POILogger; */ public final class TxMasterStyleAtom extends RecordAtom { private static final POILogger LOG = POILogFactory.getLogger(TxMasterStyleAtom.class); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; /** * Maximum number of indentation levels allowed in PowerPoint documents @@ -66,7 +69,7 @@ public final class TxMasterStyleAtom extends RecordAtom { _header = new byte[8]; System.arraycopy(source,start,_header,0,8); - _data = new byte[len-8]; + _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH); System.arraycopy(source,start+8,_data,0,_data.length); //read available styles diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java b/src/scratchpad/src/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java index 6df2aa9198..92985f4ff0 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java @@ -17,6 +17,7 @@ package org.apache.poi.hslf.record; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import java.io.IOException; import java.io.OutputStream; @@ -31,6 +32,10 @@ import java.io.OutputStream; public final class UnknownRecordPlaceholder extends RecordAtom { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + private byte[] _contents; private long _type; @@ -43,7 +48,7 @@ public final class UnknownRecordPlaceholder extends RecordAtom if(len < 0) { len = 0; } // Treat as an atom, grab and hold everything - _contents = new byte[len]; + _contents = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH); System.arraycopy(source,start,_contents,0,len); _type = LittleEndian.getUShort(_contents,2); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java index a71ebf1249..495c298157 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -90,7 +90,11 @@ import org.apache.poi.util.Units; * understanding DocSlideList and DocNotesList) - handle Slide creation cleaner */ public final class HSLFSlideShow implements SlideShow, Closeable { - /** Powerpoint document entry/stream name */ + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 10_000_000; + + /** Powerpoint document entry/stream name */ public static final String POWERPOINT_DOCUMENT = "PowerPoint Document"; enum LoadSavePhase { @@ -867,8 +871,7 @@ public final class HSLFSlideShow implements SlideShow 0) { ChunkedCipherInputStream cis = (ChunkedCipherInputStream)is; - byte plain[] = new byte[encryptionOffset]; + byte plain[] = IOUtils.safelyAllocate(encryptionOffset, MAX_RECORD_LENGTH); cis.readPlain(plain, 0, encryptionOffset); bos.write(plain); } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/HWPFOldDocument.java b/src/scratchpad/src/org/apache/poi/hwpf/HWPFOldDocument.java index d0da433f2b..74220b0de2 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/HWPFOldDocument.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/HWPFOldDocument.java @@ -38,6 +38,7 @@ import org.apache.poi.hwpf.usermodel.Range; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.CodePageUtil; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.NotImplemented; import org.apache.poi.util.POILogFactory; @@ -53,6 +54,9 @@ public class HWPFOldDocument extends HWPFDocumentCore { private static final POILogger logger = POILogFactory .getLogger( HWPFOldDocument.class ); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + private final static Charset DEFAULT_CHARSET = StringUtil.WIN_1252; private OldTextPieceTable tpt; @@ -167,7 +171,8 @@ public class HWPFOldDocument extends HWPFDocumentCore { // Generate a single Text Piece Table, with a single Text Piece // which covers all the (8 bit only) text in the file tpt = new OldTextPieceTable(); - byte[] textData = new byte[_fib.getFibBase().getFcMac()-_fib.getFibBase().getFcMin()]; + byte[] textData = IOUtils.safelyAllocate( + _fib.getFibBase().getFcMac()-_fib.getFibBase().getFcMin(), MAX_RECORD_LENGTH); System.arraycopy(_mainStream, _fib.getFibBase().getFcMin(), textData, 0, textData.length); int numChars = textData.length; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/CHPFormattedDiskPage.java b/src/scratchpad/src/org/apache/poi/hwpf/model/CHPFormattedDiskPage.java index d21e54b8da..20046ecee5 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/CHPFormattedDiskPage.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/CHPFormattedDiskPage.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.List; import org.apache.poi.hwpf.sprm.SprmBuffer; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.RecordFormatException; @@ -46,6 +47,9 @@ import org.apache.poi.util.RecordFormatException; public final class CHPFormattedDiskPage extends FormattedDiskPage { private static final int FC_SIZE = 4; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private ArrayList _chpxList = new ArrayList<>(); private ArrayList _overFlow; @@ -137,7 +141,7 @@ public final class CHPFormattedDiskPage extends FormattedDiskPage int size = LittleEndian.getUByte(_fkp, _offset + chpxOffset); - byte[] chpx = new byte[size]; + byte[] chpx = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); System.arraycopy(_fkp, _offset + ++chpxOffset, chpx, 0, size); return chpx; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/ComplexFileTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/ComplexFileTable.java index ca7bd0bfd5..9d62c9c52f 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/ComplexFileTable.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/ComplexFileTable.java @@ -31,6 +31,10 @@ import org.apache.poi.util.StringUtil; @Internal public class ComplexFileTable { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private static final byte GRPPRL_TYPE = 1; private static final byte TEXT_PIECE_TABLE_TYPE = 2; @@ -51,7 +55,7 @@ public class ComplexFileTable { offset++; int size = LittleEndian.getShort(tableStream, offset); offset += LittleEndian.SHORT_SIZE; - byte[] bs = LittleEndian.getByteArray(tableStream, offset, size); + byte[] bs = LittleEndian.getByteArray(tableStream, offset, size, MAX_RECORD_LENGTH); offset += size; SprmBuffer sprmBuffer = new SprmBuffer(bs, false, 0); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/DocumentProperties.java b/src/scratchpad/src/org/apache/poi/hwpf/model/DocumentProperties.java index 14c6981e86..c9aa4326ad 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/DocumentProperties.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/DocumentProperties.java @@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.poi.hwpf.model.types.DOPAbstractType; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @@ -33,6 +34,9 @@ import org.apache.poi.util.LittleEndian; public final class DocumentProperties extends DOPAbstractType { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private byte[] _preserved; /** @@ -51,7 +55,7 @@ public final class DocumentProperties extends DOPAbstractType if ( length != supportedSize ) { this._preserved = LittleEndian.getByteArray( tableStream, offset - + supportedSize, length - supportedSize ); + + supportedSize, length - supportedSize, MAX_RECORD_LENGTH ); } else { diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/Ffn.java b/src/scratchpad/src/org/apache/poi/hwpf/model/Ffn.java index 935d408a8e..87182333cc 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/Ffn.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/Ffn.java @@ -21,6 +21,7 @@ import java.util.Arrays; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @@ -34,6 +35,10 @@ import org.apache.poi.util.LittleEndian; @Internal public final class Ffn { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private int _cbFfnM1;//total length of FFN - 1. private byte _info; private static BitField _prq = BitFieldFactory.getInstance(0x0003);// pitch request @@ -153,7 +158,7 @@ public final class Ffn public byte[] toByteArray() { int offset = 0; - byte[] buf = new byte[this.getSize()]; + byte[] buf = IOUtils.safelyAllocate(this.getSize(), MAX_RECORD_LENGTH); buf[offset] = (byte)_cbFfnM1; offset += LittleEndian.BYTE_SIZE; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java index 36a16f9355..a8503e70ca 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java @@ -24,6 +24,7 @@ import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.Locale; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogFactory; @@ -43,6 +44,10 @@ import org.apache.poi.util.POILogger; @Internal public final class FileInformationBlock { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + public static final POILogger logger = POILogFactory .getLogger( FileInformationBlock.class ); @@ -121,8 +126,8 @@ public final class FileInformationBlock // first short is already read as _nFibNew final int fibRgCswNewLength = ( _cswNew - 1 ) * LittleEndian.SHORT_SIZE; - _fibRgCswNew = new byte[fibRgCswNewLength]; - LittleEndian.getByteArray( mainDocument, offset, fibRgCswNewLength ); + _fibRgCswNew = IOUtils.safelyAllocate(fibRgCswNewLength, MAX_RECORD_LENGTH); + LittleEndian.getByteArray( mainDocument, offset, fibRgCswNewLength, MAX_RECORD_LENGTH ); offset += fibRgCswNewLength; } else diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/ListLevel.java b/src/scratchpad/src/org/apache/poi/hwpf/model/ListLevel.java index 0e710a159e..280b7a9786 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/ListLevel.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/ListLevel.java @@ -19,6 +19,7 @@ package org.apache.poi.hwpf.model; import java.util.Arrays; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -37,6 +38,10 @@ import org.apache.poi.util.POILogger; @Internal public final class ListLevel { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private static final POILogger logger = POILogFactory .getLogger( ListLevel.class ); @@ -216,10 +221,12 @@ public final class ListLevel _lvlf = new LVLF( data, offset ); offset += LVLF.getSize(); + //short -- no need to safely allocate _grpprlPapx = new byte[_lvlf.getCbGrpprlPapx()]; System.arraycopy( data, offset, _grpprlPapx, 0, _lvlf.getCbGrpprlPapx() ); offset += _lvlf.getCbGrpprlPapx(); + //short -- no need to safely allocate _grpprlChpx = new byte[_lvlf.getCbGrpprlChpx()]; System.arraycopy( data, offset, _grpprlChpx, 0, _lvlf.getCbGrpprlChpx() ); offset += _lvlf.getCbGrpprlChpx(); @@ -279,7 +286,7 @@ public final class ListLevel public byte[] toByteArray() { - byte[] buf = new byte[getSizeInBytes()]; + byte[] buf = IOUtils.safelyAllocate(getSizeInBytes(), MAX_RECORD_LENGTH); int offset = 0; _lvlf.setCbGrpprlChpx( (short) _grpprlChpx.length ); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/OldSectionTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/OldSectionTable.java index 110a7ef565..84a02edfd0 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/OldSectionTable.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/OldSectionTable.java @@ -19,6 +19,7 @@ package org.apache.poi.hwpf.model; import java.util.Collections; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @@ -72,7 +73,7 @@ public final class OldSectionTable extends SectionTable // section properties, and we're trying to decode them as if they // were the new ones, we sometimes "need" more data than we have. // As a workaround, have a few extra 0 bytes on the end! - byte[] buf = new byte[sepxSize+2]; + byte[] buf = IOUtils.safelyAllocate(sepxSize+2, Short.MAX_VALUE+2); fileOffset += LittleEndian.SHORT_SIZE; System.arraycopy(documentStream, fileOffset, buf, 0, buf.length); sepx = new SEPX(sed, startAt, endAt, buf); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/OldTextPieceTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/OldTextPieceTable.java index 60272cad84..04c41a3087 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/OldTextPieceTable.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/OldTextPieceTable.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import org.apache.poi.util.CodePageUtil; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -32,6 +33,9 @@ public class OldTextPieceTable extends TextPieceTable { private static final POILogger logger = POILogFactory .getLogger(OldTextPieceTable.class); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000_000; + public OldTextPieceTable() { super(); } @@ -85,7 +89,7 @@ public class OldTextPieceTable extends TextPieceTable { int textSizeBytes = textSizeChars * multiple; // Grab the data that makes up the piece - byte[] buf = new byte[textSizeBytes]; + byte[] buf = IOUtils.safelyAllocate(textSizeBytes, MAX_RECORD_LENGTH); System.arraycopy(documentStream, start, buf, 0, textSizeBytes); // And now build the piece diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/PAPFormattedDiskPage.java b/src/scratchpad/src/org/apache/poi/hwpf/model/PAPFormattedDiskPage.java index 2be611a49c..8e535bc6f7 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/PAPFormattedDiskPage.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/PAPFormattedDiskPage.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @@ -167,7 +168,7 @@ public final class PAPFormattedDiskPage extends FormattedDiskPage { size--; } - byte[] papx = new byte[size]; + byte[] papx = IOUtils.safelyAllocate(size, 512); System.arraycopy(_fkp, _offset + ++papxOffset, papx, 0, size); return papx; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/PICFAndOfficeArtData.java b/src/scratchpad/src/org/apache/poi/hwpf/model/PICFAndOfficeArtData.java index c729eb2ee5..ba3293ea6a 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/PICFAndOfficeArtData.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/PICFAndOfficeArtData.java @@ -29,6 +29,9 @@ import org.apache.poi.util.LittleEndian; public class PICFAndOfficeArtData { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private List _blipRecords; private short _cchPicName; @@ -52,7 +55,7 @@ public class PICFAndOfficeArtData offset += 1; _stPicName = LittleEndian.getByteArray( dataStream, offset, - _cchPicName ); + _cchPicName, MAX_RECORD_LENGTH); offset += _cchPicName; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/PlexOfCps.java b/src/scratchpad/src/org/apache/poi/hwpf/model/PlexOfCps.java index 55e921a427..9f71f24595 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/PlexOfCps.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/PlexOfCps.java @@ -20,6 +20,7 @@ package org.apache.poi.hwpf.model; import java.util.ArrayList; import java.util.List; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @@ -32,6 +33,10 @@ import org.apache.poi.util.LittleEndian; * See page 184 of official documentation for details */ public final class PlexOfCps { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private int _iMac; private int _cbStruct; private List _props; @@ -99,7 +104,7 @@ public final class PlexOfCps { int structBufSize = +(_cbStruct * size); int bufSize = cpBufSize + structBufSize; - byte[] buf = new byte[bufSize]; + byte[] buf = IOUtils.safelyAllocate(bufSize, MAX_RECORD_LENGTH); int nodeEnd = 0; for (int x = 0; x < size; x++) { @@ -122,7 +127,7 @@ public final class PlexOfCps { int start = LittleEndian.getInt(buf, offset + getIntOffset(index)); int end = LittleEndian.getInt(buf, offset + getIntOffset(index + 1)); - byte[] struct = new byte[_cbStruct]; + byte[] struct = IOUtils.safelyAllocate(_cbStruct, MAX_RECORD_LENGTH); System.arraycopy(buf, offset + getStructOffset(index), struct, 0, _cbStruct); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java index b8f5acef9a..670554ddef 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.List; import org.apache.poi.hwpf.model.io.HWPFFileSystem; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogFactory; @@ -35,6 +36,10 @@ import org.apache.poi.util.POILogger; @Internal public class SectionTable { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private final static POILogger _logger = POILogFactory.getLogger(SectionTable.class); private static final int SED_SIZE = 12; @@ -79,7 +84,7 @@ public class SectionTable { // The first short at the offset is the size of the grpprl. int sepxSize = LittleEndian.getShort(documentStream, fileOffset); - byte[] buf = new byte[sepxSize]; + byte[] buf = IOUtils.safelyAllocate(sepxSize, MAX_RECORD_LENGTH); fileOffset += LittleEndian.SHORT_SIZE; System.arraycopy(documentStream, fileOffset, buf, 0, buf.length); _sections.add(new SEPX(sed, startAt, endAt, buf)); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/StyleDescription.java b/src/scratchpad/src/org/apache/poi/hwpf/model/StyleDescription.java index be419f5f71..2312f92d15 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/StyleDescription.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/StyleDescription.java @@ -21,6 +21,7 @@ import java.util.Arrays; import org.apache.poi.hwpf.usermodel.CharacterProperties; import org.apache.poi.hwpf.usermodel.ParagraphProperties; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogFactory; @@ -37,7 +38,9 @@ public final class StyleDescription implements HDFType { private static final POILogger logger = POILogFactory.getLogger( StyleDescription.class ); - + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + private final static int PARAGRAPH_STYLE = 1; private final static int CHARACTER_STYLE = 2; // private final static int TABLE_STYLE = 3; @@ -118,7 +121,7 @@ public final class StyleDescription implements HDFType int upxSize = LittleEndian.getShort(std, varOffset); varOffset += LittleEndian.SHORT_SIZE; - byte[] upx = new byte[upxSize]; + byte[] upx = IOUtils.safelyAllocate(upxSize, Short.MAX_VALUE); System.arraycopy(std, varOffset, upx, 0, upxSize); _upxs[x] = new UPX(upx); varOffset += upxSize; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/TextPieceTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/TextPieceTable.java index ee14b50e1e..80609bdad1 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/TextPieceTable.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/TextPieceTable.java @@ -26,6 +26,7 @@ import java.util.LinkedList; import java.util.List; import org.apache.poi.poifs.common.POIFSConstants; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -41,6 +42,9 @@ import org.apache.poi.util.POILogger; public class TextPieceTable implements CharIndexTranslator { private static final POILogger logger = POILogFactory .getLogger(TextPieceTable.class); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000_000; + // int _multiple; int _cpMin; @@ -97,7 +101,7 @@ public class TextPieceTable implements CharIndexTranslator { int textSizeBytes = textSizeChars * multiple; // Grab the data that makes up the piece - byte[] buf = new byte[textSizeBytes]; + byte[] buf = IOUtils.safelyAllocate(textSizeBytes, MAX_RECORD_LENGTH); System.arraycopy(documentStream, start, buf, 0, textSizeBytes); // And now build the piece @@ -424,7 +428,7 @@ public class TextPieceTable implements CharIndexTranslator { int mod = (offset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE); if (mod != 0) { mod = POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod; - byte[] buf = new byte[mod]; + byte[] buf = IOUtils.safelyAllocate(mod, MAX_RECORD_LENGTH); docStream.write(buf); } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmBuffer.java b/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmBuffer.java index 24ef823c49..c44e340c15 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmBuffer.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmBuffer.java @@ -19,12 +19,17 @@ package org.apache.poi.hwpf.sprm; import java.util.Arrays; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @Internal public final class SprmBuffer implements Cloneable { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + byte[] _buf; boolean _istd; int _offset; @@ -73,7 +78,7 @@ public final class SprmBuffer implements Cloneable public SprmBuffer( int sprmsStartOffset ) { - _buf = new byte[sprmsStartOffset + 4]; + _buf = IOUtils.safelyAllocate(sprmsStartOffset + 4, MAX_RECORD_LENGTH); _offset = sprmsStartOffset; _sprmsStartOffset = sprmsStartOffset; } @@ -148,7 +153,7 @@ public final class SprmBuffer implements Cloneable // commented - buffer shall not contain any additional bytes -- // sergey // byte[] newBuf = new byte[_offset + addition + 6]; - byte[] newBuf = new byte[_offset + addition]; + byte[] newBuf = IOUtils.safelyAllocate(_offset + addition, MAX_RECORD_LENGTH); System.arraycopy( _buf, 0, newBuf, 0, _buf.length ); _buf = newBuf; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmUtils.java b/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmUtils.java index 338342788c..83b9ce4888 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmUtils.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/sprm/SprmUtils.java @@ -19,6 +19,7 @@ package org.apache.poi.hwpf.sprm; import java.util.List; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @@ -26,13 +27,17 @@ import org.apache.poi.util.LittleEndian; @Internal public final class SprmUtils { + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + public SprmUtils() { } public static byte[] shortArrayToByteArray(short[] convert) { - byte[] buf = new byte[convert.length * LittleEndian.SHORT_SIZE]; + byte[] buf = IOUtils.safelyAllocate(convert.length * LittleEndian.SHORT_SIZE, MAX_RECORD_LENGTH); for (int x = 0; x < convert.length; x++) { @@ -107,7 +112,7 @@ public final class SprmUtils public static byte[] getGrpprl(List sprmList, int size) { // spit out the final grpprl - byte[] grpprl = new byte[size]; + byte[] grpprl = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); int listSize = sprmList.size() - 1; int index = 0; for (; listSize >= 0; listSize--) diff --git a/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmCompressor.java b/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmCompressor.java index 3773740a34..875b81b7fe 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmCompressor.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmCompressor.java @@ -25,12 +25,16 @@ import org.apache.poi.hwpf.usermodel.BorderCode; import org.apache.poi.hwpf.usermodel.TableAutoformatLookSpecifier; import org.apache.poi.hwpf.usermodel.TableCellDescriptor; import org.apache.poi.hwpf.usermodel.TableProperties; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; @Internal public final class TableSprmCompressor { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + public TableSprmCompressor() { } @@ -76,7 +80,9 @@ public final class TableSprmCompressor if (newTAP.getItcMac() > 0) { int itcMac = newTAP.getItcMac(); - byte[] buf = new byte[1 + (LittleEndian.SHORT_SIZE*(itcMac + 1)) + (TableCellDescriptor.SIZE*itcMac)]; + byte[] buf = IOUtils.safelyAllocate( + 1 + (LittleEndian.SHORT_SIZE*(itcMac + 1)) + (TableCellDescriptor.SIZE*itcMac), + MAX_RECORD_LENGTH); buf[0] = (byte)itcMac; short[] dxaCenters = newTAP.getRgdxaCenter();