re PR libgcj/3426 (java.io.InputStreamReader, infinite loop)
authorTom Tromey <tromey@redhat.com>
Fri, 13 Jul 2001 05:41:28 +0000 (05:41 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Fri, 13 Jul 2001 05:41:28 +0000 (05:41 +0000)
Fix for PR libgcj/3426:
* gnu/gcj/convert/natIconv.cc: Include CharConversionException.h,
errno.h.
(read): Throw exception if character conversion fails.
* java/io/BufferedInputStream.java (refill): Now package-private.
* java/io/InputStreamReader.java (ready): Simplified.
(refill): New method.
(read): Use it.

Co-Authored-By: David Brownell <david-b@pacbell.net>
From-SVN: r43975

libjava/ChangeLog
libjava/gnu/gcj/convert/natIconv.cc
libjava/java/io/BufferedInputStream.java
libjava/java/io/InputStreamReader.java

index 5a815b9ca5995e785510a73a6cad4281b1e7eb91..017a99a8cf0768a550bc64ce3d120a4eb096a657 100644 (file)
@@ -1,3 +1,15 @@
+2001-07-12  Tom Tromey  <tromey@redhat.com>
+           David Brownell  <david-b@pacbell.net>
+       
+       Fix for PR libgcj/3426:
+       * gnu/gcj/convert/natIconv.cc: Include CharConversionException.h,
+       errno.h.
+       (read): Throw exception if character conversion fails.
+       * java/io/BufferedInputStream.java (refill): Now package-private.
+       * java/io/InputStreamReader.java (ready): Simplified.
+       (refill): New method.
+       (read): Use it.
+
 2001-07-12  Tom Tromey  <tromey@redhat.com>
 
        Report from Henner Zeller:
index d346b1488f25f036b6c69bcfd48d1276f08ea553..3c5f52ec4d60e0bad74e1311b2456b3ec2b2ea47 100644 (file)
@@ -1,6 +1,6 @@
 // Input_iconv.java -- Java side of iconv() reader.
 
-/* Copyright (C) 2000  Free Software Foundation
+/* Copyright (C) 2000, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -17,8 +17,11 @@ details.  */
 
 #include <gnu/gcj/convert/Input_iconv.h>
 #include <gnu/gcj/convert/Output_iconv.h>
+#include <java/io/CharConversionException.h>
 #include <java/io/UnsupportedEncodingException.h>
 
+#include <errno.h>
+
 #ifdef HAVE_ICONV
 #include <iconv.h>
 
@@ -84,7 +87,14 @@ gnu::gcj::convert::Input_iconv::read (jcharArray outbuffer,
   size_t r = iconv_adapter (iconv, (iconv_t) handle,
                            &inbuf, &inavail,
                            &outbuf, &outavail);
-  // FIXME: what if R==-1?
+
+  if (r == (size_t) -1)
+    {
+      // Incomplete character.
+      if (errno == EINVAL)
+       return 0;
+      throw new java::io::CharConversionException ();
+    }
 
   if (iconv_byte_swap)
     {
index 6473854456b06bbdaceee491880a7bc7d44c38b3..15fa9368226512b23d2ade407846c977b94e4f51 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -131,7 +131,7 @@ public class BufferedInputStream extends FilterInputStream
     return origN - n;
   }
 
-  private boolean refill() throws IOException
+  boolean refill() throws IOException
   {
     if (markpos < 0)
       count = pos = 0;
index 03a0c3e862e13a0b9ae7a55b4e522695e9a9ea13..45fd59821ec081711f39aa4456853006e0b344dc 100644 (file)
@@ -44,6 +44,11 @@ public class InputStreamReader extends Reader
 
   private InputStreamReader(InputStream in, BytesToUnicode decoder)
   {
+    // FIXME: someone could pass in a BufferedInputStream whose buffer
+    // is smaller than the longest encoded character for this
+    // encoding.  We will probably go into an infinite loop in this
+    // case.  We probably ought to just have our own byte buffering
+    // here.
     this.in = in instanceof BufferedInputStream
               ? (BufferedInputStream) in
               : new BufferedInputStream(in);
@@ -76,28 +81,11 @@ public class InputStreamReader extends Reader
 
        if (wpos < wcount)
          return true;
-       if (work == null)
-         {
-           work = new char[100];
-           wpos = 0;
-           wcount = 0;
-         }
-       for (;;)
-         {
-           if (in.available() <= 0)
-             return false;
-           in.mark(1);
-           int b = in.read();
-           if (b < 0)
-             return true;
-           in.reset();
-           converter.setInput(in.buf, in.pos, in.count);
-           wpos = 0;
-           wcount = converter.read(work, 0, work.length);
-           in.skip(converter.inpos - in.pos);
-           if (wcount > 0)
-             return true;
-         }
+
+       // According to the spec, an InputStreamReader is ready if its
+       // input buffer is not empty (above), or if bytes are
+       // available on the underlying byte stream.
+       return in.available () > 0;
       }
   }
 
@@ -108,33 +96,23 @@ public class InputStreamReader extends Reader
        if (in == null)
          throw new IOException("Stream closed");
 
+       if (length == 0)
+         return 0;
+
        int wavail = wcount - wpos;
-       if (wavail > 0)
-         {
-           if (length > wavail)
-             length = wavail;
-           System.arraycopy(work, wpos, buf, offset, length);
-           wpos += length;
-           return length;
-         }
-       else
+       if (wavail <= 0)
          {
-           if (length == 0)
-             return 0;
-           for (;;)
-             {
-               in.mark(1);
-               int b = in.read();
-               if (b < 0)
-                 return -1;
-               in.reset();
-               converter.setInput(in.buf, in.pos, in.count);
-               int count = converter.read (buf, offset, length);
-               in.skip(converter.inpos - in.pos);
-               if (count > 0)
-                 return count;
-             }
+           // Nothing waiting, so refill our buffer.
+           if (! refill ())
+             return -1;
+           wavail = wcount - wpos;
          }
+
+       if (length > wavail)
+         length = wavail;
+       System.arraycopy(work, wpos, buf, offset, length);
+       wpos += length;
+       return length;
       }
   }
 
@@ -146,24 +124,43 @@ public class InputStreamReader extends Reader
          throw new IOException("Stream closed");
 
        int wavail = wcount - wpos;
-       if (wavail > 0)
-         return work[wpos++];
-       if (work == null)
+       if (wavail <= 0)
          {
-           work = new char[100];
-           wpos = 0;
-           wcount = 0;
+           // Nothing waiting, so refill our buffer.
+           if (! refill ())
+             return -1;
          }
-       else if (wavail == 0)
+
+       return work[wpos++];
+      }
+  }
+
+  // Read more bytes and convert them into the WORK buffer.
+  // Return false on EOF.
+  private boolean refill () throws IOException
+  {
+    wcount = wpos = 0;
+
+    if (work == null)
+      work = new char[100];
+
+    for (;;)
+      {
+       // We have knowledge of the internals of BufferedInputStream
+       // here.  Eww.
+       in.mark (0);
+       boolean r = in.refill ();
+       in.reset ();
+       if (! r)
+         return false;
+       converter.setInput(in.buf, in.pos, in.count);
+       int count = converter.read (work, wpos, work.length - wpos);
+       in.skip(converter.inpos - in.pos);
+       if (count > 0)
          {
-           wpos = 0;
-           wcount = 0;
+           wcount += count;
+           return true;
          }
-       int count = read(work, wpos, work.length-wpos);
-       if (count <= 0)
-         return -1;
-       wcount = wpos + count;
-       return work[wpos++];
       }
   }
 }