Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8287003

InputStreamReader::read() can return zero despite writing a char in the buffer

XMLWordPrintable

    • b25
    • generic
    • generic
    • Verified

        ADDITIONAL SYSTEM INFORMATION :
        Reproduced with 11.0.14, 17.0.3 and 19-ea+22 on Ubuntu 18.04.

        A DESCRIPTION OF THE PROBLEM :
        In some circumstances (see the reproducer) InputStreamReader::read(char[], int, int) can return zero while actually consuming a decoded character and writing it into the destination buffer. It happens because StreamDecoder.lockedRead() appears to assume that it's correct to always return "n + implRead(cbuf, off, off + len)" at [1], but it's not so if n == 1 and implRead() returns -1.

        Note that the reproducer below is just one of the ways to trigger the bug. Another potential case is when implReady() returns true at [2], but the stream is actually at EOF (which typically doesn't happen, but is not forbidden by the contract of ready()).

        [1] https://github.com/openjdk/jdk/blob/69ff86a32088d9664e5e0dae12edddc0643e3fd3/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java#L218
        [2] https://github.com/openjdk/jdk/blob/69ff86a32088d9664e5e0dae12edddc0643e3fd3/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java#L204

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Compile and run the following code.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        a
        1
        -1

        ACTUAL -
        a
        0
        -1


        ---------- BEGIN SOURCE ----------
        import java.io.*;
        import java.nio.charset.CodingErrorAction;
        import java.nio.charset.StandardCharsets;

        class Test {
            public static void main(String[] args) throws Exception {
                var r = new InputStreamReader(
                        new ByteArrayInputStream(new byte[] {'a', 'b', (byte) 0xC2}),
                        StandardCharsets.UTF_8.newDecoder().onMalformedInput(CodingErrorAction.IGNORE));
                System.out.println((char)r.read());
                System.out.println(r.read(new char[3], 0, 3));
                System.out.println(r.read());
            }
        }
        ---------- END SOURCE ----------

              bpb Brian Burkhalter
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: