Infinite loop in ReaderInputStream instead of throwing
exception for CodingErrorAction.REPORT.
MODIFY
src/changes/changes.xml
src/changes/changes.xml
@@ -92,6 +92,9 @@ The <action> type attribute can be add,update,fix,remove.
<action issue="IO-721" dev="ggregory" type="fix" due-to="Dirk Heinrichs, Gary Gregory">
Wrong exception message in FileUtils.setLastModified(File, File).
</action>
+ <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>
<!-- 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
@@ -228,6 +228,9 @@ private void fillBuffer() throws IOException {
}
encoderOut.compact();
lastCoderResult = encoder.encode(encoderIn, encoderOut, endOfInput);
+ if (lastCoderResult.isError()) {
+ lastCoderResult.throwException();
+ }
encoderOut.flip();
}

MODIFY
src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java
src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java
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 java.io.CharArrayReader;
import java.io.IOException;
+import java.io.InputStream;
import java.io.StringReader;
+import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Random;
+import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
public class ReaderInputStreamTest {
private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre";
@@ -57,6 +64,20 @@ public void testCharsetMismatchInfiniteLoop() throws IOException {
}
}
+ /**
+ * Tests IO-717 to avoid infinite loops.
+ *
+ * ReaderInputStream does not throw exception with {@link CodingErrorAction#REPORT}.
+ */
+ @Test
+ @Timeout(value = 500, unit = TimeUnit.MILLISECONDS)
+ public void testCodingErrorAction() throws IOException {
+ CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder().onMalformedInput(CodingErrorAction.REPORT);
+ try (InputStream in = new ReaderInputStream(new StringReader("\uD800aa"), encoder, 2)) {
+ assertThrows(CharacterCodingException.class, in::read);
+ }
+ }
+
@Test
public void testLargeUTF8WithBufferedRead() throws IOException {
testWithBufferedRead(LARGE_TEST_STRING, "UTF-8");

[IO-717] Infinite loop in ReaderInputStream instead of throwing
exception for CodingErrorAction.REPORT.