aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/poi/util/IOUtils.java
diff options
context:
space:
mode:
authorDominik Stadler <centic@apache.org>2019-12-14 13:10:17 +0000
committerDominik Stadler <centic@apache.org>2019-12-14 13:10:17 +0000
commitbefd31663f10a2059e2a1f6c7111955f4312e17b (patch)
treeb782a5b0fe8334495c33d8e5a106faae0cc6513f /src/java/org/apache/poi/util/IOUtils.java
parent57b0576f63fffcbc55afc58e3e9d186d2d8c4e72 (diff)
downloadpoi-befd31663f10a2059e2a1f6c7111955f4312e17b.tar.gz
poi-befd31663f10a2059e2a1f6c7111955f4312e17b.zip
Bug 63569: Adjust handling of check for max allocation of byte array
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1871506 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/poi/util/IOUtils.java')
-rw-r--r--src/java/org/apache/poi/util/IOUtils.java51
1 files changed, 39 insertions, 12 deletions
diff --git a/src/java/org/apache/poi/util/IOUtils.java b/src/java/org/apache/poi/util/IOUtils.java
index 1e2f12eed4..1f5214589e 100644
--- a/src/java/org/apache/poi/util/IOUtils.java
+++ b/src/java/org/apache/poi/util/IOUtils.java
@@ -42,20 +42,32 @@ 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;
+ /**
+ * The current set global allocation limit override,
+ * -1 means limits are applied per record type.
+ */
+ private static int BYTE_ARRAY_MAX_OVERRIDE = -1;
+
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.
+ * 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 allocating memory up to the size specified.
*
- * @param maxOverride The number of bytes that should be possible to be allocated in one step.
+ * It also allows to impose a lower limit than used for very memory constrained systems.
+ *
+ * Note: This is an per-allocation limit and does not allow to limit overall sum of allocations!
+ *
+ * Use -1 for using the limits specified per record-type.
+ *
+ * @param maxOverride The maximum number of bytes that should be possible to be allocated in one step.
* @since 4.0.0
*/
@SuppressWarnings("unused")
@@ -66,7 +78,7 @@ public final class IOUtils {
/**
* Peeks at the first 8 bytes of the stream. Returns those bytes, but
* with the stream unaffected. Requires a stream that supports mark/reset,
- * or a PushbackInputStream. If the stream has &gt;0 but &lt;8 bytes,
+ * or a PushbackInputStream. If the stream has &gt;0 but &lt;8 bytes,
* remaining bytes will be zero.
* @throws EmptyFileException if the stream is empty
*/
@@ -74,6 +86,12 @@ public final class IOUtils {
return peekFirstNBytes(stream, 8);
}
+ private static void checkByteSizeLimit(int length) {
+ if(BYTE_ARRAY_MAX_OVERRIDE != -1 && length > BYTE_ARRAY_MAX_OVERRIDE) {
+ throwRFE(length, BYTE_ARRAY_MAX_OVERRIDE);
+ }
+ }
+
/**
* Peeks at the first N bytes of the stream. Returns those bytes, but
* with the stream unaffected. Requires a stream that supports mark/reset,
@@ -82,6 +100,8 @@ public final class IOUtils {
* @throws EmptyFileException if the stream is empty
*/
public static byte[] peekFirstNBytes(InputStream stream, int limit) throws IOException, EmptyFileException {
+ checkByteSizeLimit(limit);
+
stream.mark(limit);
ByteArrayOutputStream bos = new ByteArrayOutputStream(limit);
copy(new BoundedInputStream(stream, limit), bos);
@@ -149,7 +169,9 @@ public final class IOUtils {
if (length > (long)Integer.MAX_VALUE) {
throw new RecordFormatException("Can't allocate an array > "+Integer.MAX_VALUE);
}
- checkLength(length, maxLength);
+ if ((length != Integer.MAX_VALUE) || (maxLength != Integer.MAX_VALUE)) {
+ checkLength(length, maxLength);
+ }
final int len = Math.min((int)length, maxLength);
ByteArrayOutputStream baos = new ByteArrayOutputStream(len == Integer.MAX_VALUE ? 4096 : len);
@@ -162,6 +184,8 @@ public final class IOUtils {
if (readBytes > 0) {
baos.write(buffer, 0, readBytes);
}
+
+ checkByteSizeLimit(readBytes);
} while (totalBytes < len && readBytes > -1);
if (maxLength != Integer.MAX_VALUE && totalBytes == maxLength) {
@@ -197,6 +221,7 @@ public final class IOUtils {
return buffer.array();
}
+ checkByteSizeLimit(length);
byte[] data = new byte[length];
buffer.get(data);
return data;
@@ -212,12 +237,12 @@ public final class IOUtils {
/**
* <p>Same as the normal {@link InputStream#read(byte[], int, int)}, but tries to ensure
* that the entire len number of bytes is read.</p>
- *
+ *
* <p>If the end of file is reached before any bytes are read, returns <tt>-1</tt>. If
* the end of the file is reached after some bytes are read, returns the
* number of bytes read. If the end of the file isn't reached before <tt>len</tt>
* bytes have been read, will return <tt>len</tt> bytes.</p>
- *
+ *
* @param in the stream from which the data is read.
* @param b the buffer into which the data is read.
* @param off the start offset in array <tt>b</tt> at which the data is written.
@@ -483,12 +508,11 @@ public final class IOUtils {
}
return sum.getValue();
}
-
-
+
/**
* Quietly (no exceptions) close Closable resource. In case of error it will
* be printed to {@link IOUtils} class logger.
- *
+ *
* @param closeable
* resource to close
*/
@@ -570,6 +594,9 @@ public final class IOUtils {
public static byte[] safelyAllocate(long length, int maxLength) {
safelyAllocateCheck(length, maxLength);
+
+ checkByteSizeLimit((int)length);
+
return new byte[(int)length];
}