From: Tom Tromey Date: Fri, 13 Jul 2001 05:41:28 +0000 (+0000) Subject: re PR libgcj/3426 (java.io.InputStreamReader, infinite loop) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a9a399fe24303d933a412f01c01bb8e78d97cf9f;p=gcc.git 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 From-SVN: r43975 --- diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 5a815b9ca59..017a99a8cf0 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,15 @@ +2001-07-12 Tom Tromey + David Brownell + + 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 Report from Henner Zeller: diff --git a/libjava/gnu/gcj/convert/natIconv.cc b/libjava/gnu/gcj/convert/natIconv.cc index d346b1488f2..3c5f52ec4d6 100644 --- a/libjava/gnu/gcj/convert/natIconv.cc +++ b/libjava/gnu/gcj/convert/natIconv.cc @@ -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 #include +#include #include +#include + #ifdef HAVE_ICONV #include @@ -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) { diff --git a/libjava/java/io/BufferedInputStream.java b/libjava/java/io/BufferedInputStream.java index 6473854456b..15fa9368226 100644 --- a/libjava/java/io/BufferedInputStream.java +++ b/libjava/java/io/BufferedInputStream.java @@ -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; diff --git a/libjava/java/io/InputStreamReader.java b/libjava/java/io/InputStreamReader.java index 03a0c3e862e..45fd59821ec 100644 --- a/libjava/java/io/InputStreamReader.java +++ b/libjava/java/io/InputStreamReader.java @@ -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++]; } } }