summaryrefslogtreecommitdiffstats
path: root/poi
diff options
context:
space:
mode:
authorDominik Stadler <centic@apache.org>2021-12-05 15:33:58 +0000
committerDominik Stadler <centic@apache.org>2021-12-05 15:33:58 +0000
commit3ef9605d292d82581450b999e1fe9b4cc4ce5208 (patch)
treedc9664e6528025c4a467c7b2ad93ebaffad3c0bb /poi
parentd5538d24d83aa2feb67c57909211bfaae673c989 (diff)
downloadpoi-3ef9605d292d82581450b999e1fe9b4cc4ce5208.tar.gz
poi-3ef9605d292d82581450b999e1fe9b4cc4ce5208.zip
Fix issues found when fuzzing Apache POI via Jazzer
Fix IOUtils.safelyClone to prevent overly large allocations properly also when length is larger than src.length Throw an exception instead of an assertion which hides invalid usage in production builds git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1895597 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'poi')
-rw-r--r--poi/src/main/java/org/apache/poi/util/IOUtils.java12
-rw-r--r--poi/src/test/java/org/apache/poi/util/TestIOUtils.java47
2 files changed, 56 insertions, 3 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 09bb25a9cb..a3ac29ddbb 100644
--- a/poi/src/main/java/org/apache/poi/util/IOUtils.java
+++ b/poi/src/main/java/org/apache/poi/util/IOUtils.java
@@ -501,9 +501,15 @@ public final class IOUtils {
if (src == null) {
return null;
}
- assert(offset >= 0 && length >= 0 && maxLength >= 0);
- safelyAllocateCheck(Math.min(src.length-offset,length), maxLength);
- return Arrays.copyOfRange(src, offset, offset+length);
+
+ if (offset < 0 || length < 0 || maxLength < 0) {
+ throw new RecordFormatException("Invalid offset/length specified: "
+ + "offset: " + offset + ", lenght: " + length + ", maxLength: " + maxLength);
+ }
+
+ int realLength = Math.min(src.length - offset, length);
+ safelyAllocateCheck(realLength, maxLength);
+ return Arrays.copyOfRange(src, offset, offset+realLength);
}
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 5a0c5c5bdb..e5a70fa3bb 100644
--- a/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
+++ b/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
@@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -442,6 +443,52 @@ final class TestIOUtils {
() -> IOUtils.calculateChecksum(new NullInputStream(1, true)));
}
+ @Test
+ void testSafelyCloneNull() {
+ assertNull(IOUtils.safelyClone(null, 0, 0, 0));
+ }
+
+ @Test
+ void testSafelyCloneInvalid() {
+ assertThrows( RecordFormatException.class,
+ () -> IOUtils.safelyClone(new byte[0], -1, 0, 0));
+ assertThrows( RecordFormatException.class,
+ () -> IOUtils.safelyClone(new byte[0], 0, -2, 0));
+ assertThrows( RecordFormatException.class,
+ () -> IOUtils.safelyClone(new byte[0], 0, 0, -3));
+ }
+
+ @Test
+ void testSafelyCloneEmpty() {
+ byte[] bytes = new byte[0];
+ byte[] ret = IOUtils.safelyClone(bytes, 0, 0, 0);
+ assertNotNull(ret);
+ assertEquals(0, ret.length);
+ }
+
+ @Test
+ void testSafelyCloneDataButLengthLimit() {
+ byte[] bytes = new byte[] { 1, 2, 3, 4 };
+ assertThrows( RecordFormatException.class,
+ () -> IOUtils.safelyClone(bytes, 0, bytes.length, 0));
+ }
+
+ @Test
+ void testSafelyCloneData() {
+ byte[] bytes = new byte[] { 1, 2, 3, 4 };
+ byte[] ret = IOUtils.safelyClone(bytes, 0, bytes.length, 100);
+ assertNotNull(ret);
+ assertEquals(4, ret.length);
+ }
+
+ @Test
+ void testSafelyCloneDataHugeLength() {
+ byte[] bytes = new byte[] { 1, 2, 3, 4 };
+ byte[] ret = IOUtils.safelyClone(bytes, 0, Integer.MAX_VALUE, 100);
+ assertNotNull(ret);
+ assertEquals(4, ret.length);
+ }
+
/**
* This returns 0 for the first call to skip and then reads
* as requested. This tests that the fallback to read() works.