ReaderInputStream enter infinite loop for too small buffer
sizes.
MODIFY
src/changes/changes.xml
src/changes/changes.xml
@@ -95,6 +95,9 @@ The <action> type attribute can be add,update,fix,remove.
<action issue="IO-717" dev="ggregory" type="fix" due-to="Marcono1234, Gary Gregory">
Infinite loop in ReaderInputStream instead of throwing exception for CodingErrorAction.REPORT.
</action>
+ <action issue="IO-716" dev="ggregory" type="fix" due-to="Marcono1234, Gary Gregory">
+ ReaderInputStream enter infinite loop for too small buffer sizes.
+ </action>
<!-- ADD -->
<action dev="ggregory" type="add" due-to="Gary Gregory">
Add BrokenReader.INSTANCE.

MODIFY
src/main/java/org/apache/commons/io/input/ReaderInputStream.java
src/main/java/org/apache/commons/io/input/ReaderInputStream.java
public class ReaderInputStream extends InputStream {
private static final int DEFAULT_BUFFER_SIZE = 1024;
+ private static int checkBufferSize(int bufferSize) {
+ if (bufferSize < 2) {
+ throw new IllegalArgumentException("Buffer size < 2");
+ }
+ return bufferSize;
+ }
private final Reader reader;
+
private final CharsetEncoder encoder;
/**
* buffer provided by the caller.
*/
private final ByteBuffer encoderOut;
-
private CoderResult lastCoderResult;
+
private boolean endOfInput;
/**
@@ -131,9 +138,9 @@ public ReaderInputStream(final Reader reader, final Charset charset) {
/**
* Constructs a new {@link ReaderInputStream}.
*
- * @param reader the target {@link Reader}
- * @param charset the charset encoding
- * @param bufferSize the size of the input buffer in number of characters
+ * @param reader the target {@link Reader}.
+ * @param charset the charset encoding.
+ * @param bufferSize the size of the input buffer in number of characters.
*/
public ReaderInputStream(final Reader reader, final Charset charset, final int bufferSize) {
// @formatter:off
@@ -141,7 +148,7 @@ public ReaderInputStream(final Reader reader, final Charset charset, final int b
charset.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE),
- bufferSize);
+ checkBufferSize(bufferSize));
// @formatter:on
}

MODIFY
src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java
src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java
package org.apache.commons.io.input;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.CharArrayReader;
import java.io.IOException;
private final Random random = new Random();
+ @Test
+ public void testBufferTooSmall() throws IOException {
+ assertThrows(IllegalArgumentException.class, () -> new ReaderInputStream(new StringReader("\uD800"), StandardCharsets.UTF_8, 1));
+ }
+
+ @Test
+ @Timeout(value = 500, unit = TimeUnit.MILLISECONDS)
+ public void testBufferSmallest() throws IOException {
+ try (InputStream in = new ReaderInputStream(new StringReader("\uD800"), StandardCharsets.UTF_8, 2)) {
+ in.read();
+ }
+ }
+
/*
* Tests https://issues.apache.org/jira/browse/IO-277
*/

[IO-716] ReaderInputStream enter infinite loop for too small buffer
sizes.