You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by pk...@apache.org on 2025/10/03 18:43:52 UTC
(commons-io) 01/01: Fix inconsistent exception in `IOUtils.toByteArray`
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch fix/io-utils-eof
in repository https://gitbox.apache.org/repos/asf/commons-io.git
commit 792947fc0552a984da52e2c6f42d61311361a6c8
Author: Piotr P. Karwasz <pk...@apache.org>
AuthorDate: Fri Oct 3 20:40:43 2025 +0200
Fix inconsistent exception in `IOUtils.toByteArray`
The implementation of `IOUtils.toByteArray(InputStream, int, int)` added in #776 throws different exceptions depending on the requested size:
* For request sizes larger than the internal chunk size, it correctly throws an `EOFException`.
* For smaller requests, it incorrectly throws a generic `IOException`.
This PR makes the behavior consistent by always throwing an `EOFException` when the stream ends prematurely.
Note: This also affects `RandomAccessFiles.read`. Its previous truncation behavior was undocumented and inconsistent with `RandomAccessFile.read` (which reads as much as possible). The new behavior is not explicitly documented here either, since it is unclear whether throwing on truncation is actually desirable.
---
src/main/java/org/apache/commons/io/IOUtils.java | 3 ++-
src/test/java/org/apache/commons/io/IOUtilsTest.java | 11 ++++++++++-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java
index a882d4d87..e157d51a5 100644
--- a/src/main/java/org/apache/commons/io/IOUtils.java
+++ b/src/main/java/org/apache/commons/io/IOUtils.java
@@ -2957,6 +2957,7 @@ public static byte[] toByteArray(final InputStream input, final long size) throw
* @param input the input to read, not null.
* @param size the size of the input to read, where 0 < {@code size} <= length of input.
* @return byte [] of length {@code size}.
+ * @throws EOFException if the end of the input is reached before reading {@code size} bytes.
* @throws IOException if an I/O error occurs or input length is smaller than parameter {@code size}.
* @throws IllegalArgumentException if {@code size} is less than zero.
*/
@@ -2974,7 +2975,7 @@ static byte[] toByteArray(final IOTriFunction<byte[], Integer, Integer, Integer>
offset += read;
}
if (offset != size) {
- throw new IOException("Unexpected read size, current: " + offset + ", expected: " + size);
+ throw new EOFException("Unexpected read size, current: " + offset + ", expected: " + size);
}
return data;
}
diff --git a/src/test/java/org/apache/commons/io/IOUtilsTest.java b/src/test/java/org/apache/commons/io/IOUtilsTest.java
index 02574946b..df05c648f 100644
--- a/src/test/java/org/apache/commons/io/IOUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/IOUtilsTest.java
@@ -158,7 +158,9 @@ static Stream<Arguments> testToByteArray_InputStream_Size_BufferSize_Throws() {
Arguments.of(-1, 128, IllegalArgumentException.class),
// Invalid buffer size
Arguments.of(0, 0, IllegalArgumentException.class),
- // Huge size: should not cause OutOfMemoryError
+ // Truncation with requested size < chunk size
+ Arguments.of(64, 128, EOFException.class),
+ // Truncation with requested size > chunk size
Arguments.of(Integer.MAX_VALUE, 128, EOFException.class));
}
@@ -1757,6 +1759,13 @@ void testToByteArray_InputStream_Size() throws Exception {
}
}
+ @Test
+ void testToByteArray_InputStream_Size_Truncated() throws Exception {
+ try (InputStream in = new NullInputStream(0)) {
+ assertThrows(EOFException.class, () -> IOUtils.toByteArray(in, 1), "Should have failed with EOFException");
+ }
+ }
+
@ParameterizedTest
@MethodSource
void testToByteArray_InputStream_Size_BufferSize_Succeeds(final byte[] data, final int size, final int bufferSize) throws IOException {