Commit a9a399fe by Tom Tromey Committed by Tom Tromey

re PR libgcj/3426 (java.io.InputStreamReader, infinite loop)


	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
parent c813baa4
2001-07-12 Tom Tromey <tromey@redhat.com> 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: Report from Henner Zeller:
* java/io/FileOutputStream.java (FileOutputStream): Throw * java/io/FileOutputStream.java (FileOutputStream): Throw
......
// Input_iconv.java -- Java side of iconv() reader. // 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. This file is part of libgcj.
...@@ -17,8 +17,11 @@ details. */ ...@@ -17,8 +17,11 @@ details. */
#include <gnu/gcj/convert/Input_iconv.h> #include <gnu/gcj/convert/Input_iconv.h>
#include <gnu/gcj/convert/Output_iconv.h> #include <gnu/gcj/convert/Output_iconv.h>
#include <java/io/CharConversionException.h>
#include <java/io/UnsupportedEncodingException.h> #include <java/io/UnsupportedEncodingException.h>
#include <errno.h>
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
#include <iconv.h> #include <iconv.h>
...@@ -84,7 +87,14 @@ gnu::gcj::convert::Input_iconv::read (jcharArray outbuffer, ...@@ -84,7 +87,14 @@ gnu::gcj::convert::Input_iconv::read (jcharArray outbuffer,
size_t r = iconv_adapter (iconv, (iconv_t) handle, size_t r = iconv_adapter (iconv, (iconv_t) handle,
&inbuf, &inavail, &inbuf, &inavail,
&outbuf, &outavail); &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) if (iconv_byte_swap)
{ {
......
/* Copyright (C) 1998, 1999 Free Software Foundation /* Copyright (C) 1998, 1999, 2001 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -131,7 +131,7 @@ public class BufferedInputStream extends FilterInputStream ...@@ -131,7 +131,7 @@ public class BufferedInputStream extends FilterInputStream
return origN - n; return origN - n;
} }
private boolean refill() throws IOException boolean refill() throws IOException
{ {
if (markpos < 0) if (markpos < 0)
count = pos = 0; count = pos = 0;
......
...@@ -44,6 +44,11 @@ public class InputStreamReader extends Reader ...@@ -44,6 +44,11 @@ public class InputStreamReader extends Reader
private InputStreamReader(InputStream in, BytesToUnicode decoder) 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 this.in = in instanceof BufferedInputStream
? (BufferedInputStream) in ? (BufferedInputStream) in
: new BufferedInputStream(in); : new BufferedInputStream(in);
...@@ -76,28 +81,11 @@ public class InputStreamReader extends Reader ...@@ -76,28 +81,11 @@ public class InputStreamReader extends Reader
if (wpos < wcount) if (wpos < wcount)
return true; return true;
if (work == null)
{ // According to the spec, an InputStreamReader is ready if its
work = new char[100]; // input buffer is not empty (above), or if bytes are
wpos = 0; // available on the underlying byte stream.
wcount = 0; return in.available () > 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;
}
} }
} }
...@@ -108,33 +96,23 @@ public class InputStreamReader extends Reader ...@@ -108,33 +96,23 @@ public class InputStreamReader extends Reader
if (in == null) if (in == null)
throw new IOException("Stream closed"); throw new IOException("Stream closed");
if (length == 0)
return 0;
int wavail = wcount - wpos; int wavail = wcount - wpos;
if (wavail > 0) if (wavail <= 0)
{
if (length > wavail)
length = wavail;
System.arraycopy(work, wpos, buf, offset, length);
wpos += length;
return length;
}
else
{ {
if (length == 0) // Nothing waiting, so refill our buffer.
return 0; if (! refill ())
for (;;) return -1;
{ wavail = wcount - wpos;
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;
}
} }
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 ...@@ -146,24 +124,43 @@ public class InputStreamReader extends Reader
throw new IOException("Stream closed"); throw new IOException("Stream closed");
int wavail = wcount - wpos; int wavail = wcount - wpos;
if (wavail > 0) if (wavail <= 0)
return work[wpos++];
if (work == null)
{ {
work = new char[100]; // Nothing waiting, so refill our buffer.
wpos = 0; if (! refill ())
wcount = 0; 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 += count;
wcount = 0; return true;
} }
int count = read(work, wpos, work.length-wpos);
if (count <= 0)
return -1;
wcount = wpos + count;
return work[wpos++];
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment