This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
commit 7e0d317ac61427e6004372622df4014c1e602487 Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Sun May 16 10:26:40 2021 -0400 [IO-429] Check for long streams in IOUtils.toByteArray #175. --- src/changes/changes.xml | 3 +++ src/main/java/org/apache/commons/io/IOUtils.java | 14 ++++++++++---- src/test/java/org/apache/commons/io/IOUtilsTestCase.java | 9 +++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3bdcbbb..87524e3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -126,6 +126,9 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" type="fix" due-to="Rob Spoor, Gary Gregory"> Prevent infinite loop with AbstractCharacterFilterReader if EOF is filtered out #226. </action> + <action issue="IO-429" dev="ggregory" type="fix" due-to="Rob Spoor, Ivan Leskin"> + Check for long streams in IOUtils.toByteArray #175. + </action> <!-- ADD --> <action dev="ggregory" type="add" due-to="Gary Gregory"> Add FileSystemProviders class. diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java index eaf5856..624d7a0 100644 --- a/src/main/java/org/apache/commons/io/IOUtils.java +++ b/src/main/java/org/apache/commons/io/IOUtils.java @@ -55,6 +55,7 @@ import org.apache.commons.io.output.AppendableWriter; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.io.output.StringBuilderWriter; +import org.apache.commons.io.output.ThresholdingOutputStream; import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; /** @@ -2394,12 +2395,17 @@ public class IOUtils { * @param inputStream the {@code InputStream} to read. * @return the requested byte array. * @throws NullPointerException if the InputStream is {@code null}. - * @throws IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs or reading more than {@link Integer#MAX_VALUE} occurs. */ public static byte[] toByteArray(final InputStream inputStream) throws IOException { - try (final UnsynchronizedByteArrayOutputStream output = new UnsynchronizedByteArrayOutputStream()) { - copy(inputStream, output); - return output.toByteArray(); + // We use a ThresholdingOutputStream to avoid reading AND writing more than Integer.MAX_VALUE. + try (final UnsynchronizedByteArrayOutputStream ubaOutput = new UnsynchronizedByteArrayOutputStream(); + final ThresholdingOutputStream thresholdOuput = new ThresholdingOutputStream(Integer.MAX_VALUE, os -> { + throw new IllegalArgumentException( + String.format("Cannot read more than %,d into a byte array", Integer.MAX_VALUE)); + }, os -> ubaOutput)) { + copy(inputStream, thresholdOuput); + return ubaOutput.toByteArray(); } } diff --git a/src/test/java/org/apache/commons/io/IOUtilsTestCase.java b/src/test/java/org/apache/commons/io/IOUtilsTestCase.java index 5e89881..106729b 100644 --- a/src/test/java/org/apache/commons/io/IOUtilsTestCase.java +++ b/src/test/java/org/apache/commons/io/IOUtilsTestCase.java @@ -62,6 +62,7 @@ import java.util.Arrays; import java.util.List; import org.apache.commons.io.function.IOConsumer; +import org.apache.commons.io.input.CircularInputStream; import org.apache.commons.io.input.NullInputStream; import org.apache.commons.io.output.AppendableWriter; import org.apache.commons.io.output.NullOutputStream; @@ -69,6 +70,7 @@ import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.io.test.TestUtils; import org.apache.commons.io.test.ThrowOnCloseReader; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -1436,6 +1438,13 @@ public class IOUtilsTestCase { } @Test + @Disabled("Disable by default as it uses too much memory and can cause builds to fail.") + public void testToByteArray_InputStream_LongerThanIntegerMaxValue() throws Exception { + final CircularInputStream cin = new CircularInputStream(IOUtils.byteArray(), Integer.MAX_VALUE + 1L); + assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(cin)); + } + + @Test public void testToByteArray_InputStream_NegativeSize() throws Exception { try (FileInputStream fin = new FileInputStream(testFile)) {