This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: PR 3426 fix


I'm checking this in on the trunk.
This fixes PR 3426.

Basically, InputStreamReader would go into an infinite loop if its
work buffer had a partial character at the end.  Also, the iconv
converter failed to do anything sensible when a conversion error was
encountered.

Thanks to David Brownell for testing the first patch and suggesting
the fixes which are incorporated.

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.


Tom

Index: gnu/gcj/convert/natIconv.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/convert/natIconv.cc,v
retrieving revision 1.8
diff -u -r1.8 natIconv.cc
--- gnu/gcj/convert/natIconv.cc 2000/11/01 17:00:01 1.8
+++ gnu/gcj/convert/natIconv.cc 2001/07/13 05:37:17
@@ -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 @@
 
 #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 @@
   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: java/io/BufferedInputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/BufferedInputStream.java,v
retrieving revision 1.3
diff -u -r1.3 BufferedInputStream.java
--- java/io/BufferedInputStream.java 2000/03/07 19:55:26 1.3
+++ java/io/BufferedInputStream.java 2001/07/13 05:37:17
@@ -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 @@
     return origN - n;
   }
 
-  private boolean refill() throws IOException
+  boolean refill() throws IOException
   {
     if (markpos < 0)
       count = pos = 0;
Index: java/io/InputStreamReader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/InputStreamReader.java,v
retrieving revision 1.8
diff -u -r1.8 InputStreamReader.java
--- java/io/InputStreamReader.java 2001/02/09 01:54:38 1.8
+++ java/io/InputStreamReader.java 2001/07/13 05:37:18
@@ -44,6 +44,11 @@
 
   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 @@
 
 	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 @@
 	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 @@
 	  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++];
       }
   }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]