aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPJ Fanning <fanningpj@apache.org>2022-03-12 13:57:50 +0000
committerPJ Fanning <fanningpj@apache.org>2022-03-12 13:57:50 +0000
commit3573e5c44fbd48bc518baaeb7a04f08ee04312e3 (patch)
tree58ceaa99151fe025c69472840d5302594937e329
parent1efd809e6c61fffb899189b9133e7ba89c36038d (diff)
downloadpoi-3573e5c44fbd48bc518baaeb7a04f08ee04312e3.tar.gz
poi-3573e5c44fbd48bc518baaeb7a04f08ee04312e3.zip
handle case where toByteArray truncates stream because max len is less than stream len
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1898876 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--poi/src/main/java/org/apache/poi/util/IOUtils.java27
-rw-r--r--poi/src/test/java/org/apache/poi/util/TestIOUtils.java37
2 files changed, 53 insertions, 11 deletions
diff --git a/poi/src/main/java/org/apache/poi/util/IOUtils.java b/poi/src/main/java/org/apache/poi/util/IOUtils.java
index 7e1fef8990..cf40645138 100644
--- a/poi/src/main/java/org/apache/poi/util/IOUtils.java
+++ b/poi/src/main/java/org/apache/poi/util/IOUtils.java
@@ -230,7 +230,7 @@ public final class IOUtils {
checkLength(length, derivedMaxLength);
}
- final int derivedLen = Math.min(length, derivedMaxLength);
+ final int derivedLen = isLengthKnown ? Math.min(length, derivedMaxLength) : derivedMaxLength;
final int byteArrayInitLen = calculateByteArrayInitLength(isLengthKnown, length, derivedMaxLength);
final int internalBufferLen = DEFAULT_BUFFER_SIZE;
try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(byteArrayInitLen)) {
@@ -242,18 +242,15 @@ public final class IOUtils {
if (readBytes > 0) {
baos.write(buffer, 0, readBytes);
}
-
checkByteSizeLimit(totalBytes);
} while (totalBytes < derivedLen && readBytes > -1);
- if (checkEOFException) {
- if (derivedMaxLength != Integer.MAX_VALUE && totalBytes == derivedMaxLength) {
- throw new IOException("MaxLength (" + derivedMaxLength + ") reached - stream seems to be invalid.");
- }
+ if (BYTE_ARRAY_MAX_OVERRIDE < 0 && readBytes > -1 && !isLengthKnown && stream.read() >= 0) {
+ throwRecordTruncationException(derivedMaxLength);
+ }
- if (derivedLen != Integer.MAX_VALUE && totalBytes < derivedLen) {
- throw new EOFException("unexpected EOF - expected len: " + derivedLen + " - actual len: " + totalBytes);
- }
+ if (checkEOFException && derivedLen != Integer.MAX_VALUE && totalBytes < derivedLen) {
+ throw new EOFException("unexpected EOF - expected len: " + derivedLen + " - actual len: " + totalBytes);
}
return baos.toByteArray();
@@ -586,7 +583,7 @@ public final class IOUtils {
* Simple utility function to check that you haven't hit EOF
* when reading a byte.
*
- * @param is inputstream to read
+ * @param is input stream to read
* @return byte read, unless
* @throws IOException on IOException or EOF if -1 is read
*/
@@ -608,4 +605,14 @@ public final class IOUtils {
length, maxLength));
}
+
+ private static void throwRecordTruncationException(final int maxLength) {
+ throw new RecordFormatException(String.format(Locale.ROOT, "Tried to read data but the maximum length " +
+ "for this record type is %,d.\n" +
+ "If the file is not corrupt or large, 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()", maxLength));
+
+ }
}
diff --git a/poi/src/test/java/org/apache/poi/util/TestIOUtils.java b/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
index 1f55e980f6..cb335921cb 100644
--- a/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
+++ b/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
@@ -152,6 +152,30 @@ final class TestIOUtils {
}
@Test
+ void testToByteArrayMaxLengthWithByteArrayInitLenShort() throws IOException {
+ final byte[] array = new byte[]{1, 2, 3, 4, 5, 6, 7};
+ IOUtils.setMaxByteArrayInitSize(2);
+ try (ByteArrayInputStream is = new ByteArrayInputStream(array)) {
+ assertEquals(2, IOUtils.getMaxByteArrayInitSize());
+ assertArrayEquals(array, IOUtils.toByteArrayWithMaxLength(is, 7));
+ } finally {
+ IOUtils.setMaxByteArrayInitSize(-1);
+ }
+ }
+
+ @Test
+ void testToByteArrayMaxLengthWithByteArrayInitLenLong() throws IOException {
+ final byte[] array = new byte[]{1, 2, 3, 4, 5, 6, 7};
+ IOUtils.setMaxByteArrayInitSize(8192);
+ try (ByteArrayInputStream is = new ByteArrayInputStream(array)) {
+ assertEquals(8192, IOUtils.getMaxByteArrayInitSize());
+ assertArrayEquals(array, IOUtils.toByteArrayWithMaxLength(is, 7));
+ } finally {
+ IOUtils.setMaxByteArrayInitSize(-1);
+ }
+ }
+
+ @Test
void testToByteArrayMaxLengthLongerThanArray() throws IOException {
final byte[] array = new byte[]{1, 2, 3, 4, 5, 6, 7};
try (ByteArrayInputStream is = new ByteArrayInputStream(array)) {
@@ -163,7 +187,18 @@ final class TestIOUtils {
void testToByteArrayMaxLengthShorterThanArray() throws IOException {
final byte[] array = new byte[]{1, 2, 3, 4, 5, 6, 7};
try (ByteArrayInputStream is = new ByteArrayInputStream(array)) {
- assertArrayEquals(new byte[]{1, 2, 3}, IOUtils.toByteArrayWithMaxLength(is, 3));
+ assertThrows(RecordFormatException.class, () -> IOUtils.toByteArrayWithMaxLength(is, 3));
+ }
+ }
+
+ @Test
+ void testToByteArrayMaxLengthShorterThanArrayWithByteArrayOverride() throws IOException {
+ final byte[] array = new byte[]{1, 2, 3, 4, 5, 6, 7};
+ IOUtils.setByteArrayMaxOverride(30 * 1024 * 1024);
+ try (ByteArrayInputStream is = new ByteArrayInputStream(array)) {
+ assertArrayEquals(array, IOUtils.toByteArrayWithMaxLength(is, 3));
+ } finally {
+ IOUtils.setByteArrayMaxOverride(-1);
}
}