public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* java/3426: java.io.InputStreamReader, infinite loop
@ 2001-06-26  8:16 david-b
  0 siblings, 0 replies; 10+ messages in thread
From: david-b @ 2001-06-26  8:16 UTC (permalink / raw)
  To: gcc-gnats

>Number:         3426
>Category:       java
>Synopsis:       java.io.InputStreamReader, infinite loop
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jun 26 08:16:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     david-b@pacbell.ne
>Release:        gcj 3.0
>Organization:
>Environment:
RedHat 7.0, i686-pc-linux-gnu
>Description:
The for(;;) loop in the second half of java.io.InputStreamReader
will loop infinitely in the following case:

- two bytes left at the end of the buffered stream

- using a multibyte encoding, such as iso-2022-jpase, or
  shift_jis

- the character being read takes more than two bytes

In that case the converter.read() machinery tries to
report ("wcount = 0"?) an incomplete read, but there
seems to be no mechanism in place to

 (a) shift the remaining bytes to the beginning
     of the BufferedInputStream
 (b) read more bytes, so that converter.read()
     can progress

So the for(;;)  inside read() will never terminate,
since each pass only proceeds by zero bytes.
>How-To-Repeat:
Use the SAX/XML test suite at http://xmlconf.sourceforge.net
and reconfigure the GCJ version not to make special cases
for the two biggish (200K) Japanese translations of a draft
of the XML spec (pr-xml-iso-2022-jp, pr-xml-shift_jis).
The GDB work characterized here used the first of those,
I'm assuming the second loop is the same bug.

(You'll need the "java/lib" and "xml" modules from CVS
there.  Sorry I don't have a small test case.)
>Fix:
Note that inside gnu/gcj/convert/natIconv.cc there is a
"FIXME:  what if R == -1 ?" comment which seems like it
is what's being hit here.  Suggested fix there is to
return -1 in that case, and throw an exception in the
#else /* !HAVE_ICONV */ branch using "-1" as some sort
of error, passing the iconv convention up a layer.

Then InputStreamReader.read() does need logic for (a), (b).
>Release-Note:
>Audit-Trail:
>Unformatted:


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-07-12 22:56 David Brownell
  0 siblings, 0 replies; 10+ messages in thread
From: David Brownell @ 2001-07-12 22:56 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: David Brownell <david-b@pacbell.net>
To: tromey@redhat.com
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: Thu, 12 Jul 2001 22:50:00 -0700

 > David> With this patch, the infinite loop is gone.  Some of the other
 > David> InputStreamReader strangeness I'd mentioned is still there.
 > 
 > Is this info in the PR?  I thought the patch addressed everything.
 
 Some info was mentioned in the original email I sent, before I
 filed the PR for that particular sub-problem.  It wasn't an infinite
 loop -- other strangeness, with no solid characterization yet.
 Secondary symptoms included null pointer exceptions.
 
 - Dave
 
 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-07-12 22:36 Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2001-07-12 22:36 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: Tom Tromey <tromey@redhat.com>
To: David Brownell <david-b@pacbell.net>
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: 12 Jul 2001 23:56:35 -0600

 >>>>> "David" == David Brownell <david-b@pacbell.net> writes:
 
 David> Didn't quite do it ... two bugs: inverting status of refill()
 David> once too many, and not initializing "work".
 
 Sorry about all the follow-ups.
 I decided to initialize `work' in the `refill' method.
 I also used a smaller buffer size.  This is more in keeping with the
 original code.  (I don't know what tradeoffs, if any, resulted in the
 number 100 being used.  Bummer.)
 
 Tom


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-07-12 22:36 Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2001-07-12 22:36 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: Tom Tromey <tromey@redhat.com>
To: David Brownell <david-b@pacbell.net>
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: 12 Jul 2001 23:53:41 -0600

 >>>>> "David" == David Brownell <david-b@pacbell.net> writes:
 
 David> Didn't quite do it ... two bugs: inverting status of refill()
 David> once too many, and not initializing "work".  This updated patch
 David> was behaving OK for me (includes the natIconv.cc fix) ...
 
 Thanks for testing this.  I agree with your changes and I'll be
 checking it in soon.
 
 David> apologies for sending as an attachment, this mailer isn't
 David> reliable otherwise.
 
 Attachments are fine.  My mailer understands them, and as you say they
 are reliably decodable.
 
 David> With this patch, the infinite loop is gone.  Some of the other
 David> InputStreamReader strangeness I'd mentioned is still there.
 
 Is this info in the PR?  I thought the patch addressed everything.
 
 Tom


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-07-12 21:36 Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2001-07-12 21:36 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: Tom Tromey <tromey@redhat.com>
To: David Brownell <david-b@pacbell.net>
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: 12 Jul 2001 22:54:57 -0600

 >>>>> "David" == David Brownell <david-b@pacbell.net> writes:
 
 >> Hi David.  Could you try this untested patch and see if it helps this
 >> problem?
 
 David> Didn't quite do it ... two bugs: inverting status of refill()
 David> once too many, and not initializing "work".  This updated patch
 David> was behaving OK for me (includes the natIconv.cc fix)
 David> ... apologies for sending as an attachment, this mailer isn't
 David> reliable otherwise.
 
 Thanks for the patch.  I'll try to get to it soon now.  Maybe
 tomorrow.
 
 Tom


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-07-04 23:56 David Brownell
  0 siblings, 0 replies; 10+ messages in thread
From: David Brownell @ 2001-07-04 23:56 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: David Brownell <david-b@pacbell.net>
To: tromey@redhat.com
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: Wed, 04 Jul 2001 23:47:47 -0700

 This is a multi-part message in MIME format.
 
 --Boundary_(ID_byZdqokn58HeX4394FLC+Q)
 Content-type: text/plain; charset=iso-8859-1
 Content-transfer-encoding: 7BIT
 
 > Hi David.  Could you try this untested patch and see if it helps this
 > problem?
 
 Didn't quite do it ... two bugs:  inverting status of refill() once
 too many, and not initializing "work".  This updated patch was
 behaving OK for me (includes the natIconv.cc fix) ... apologies
 for sending as an attachment, this mailer isn't reliable otherwise.
 
 With this patch, the infinite loop is gone.  Some of the other
 InputStreamReader strangeness I'd mentioned is still there.
 
 - Dave
 
 
 --Boundary_(ID_byZdqokn58HeX4394FLC+Q)
 Content-type: application/octet-stream; name=libgcj.patch
 Content-transfer-encoding: quoted-printable
 Content-disposition: attachment; filename=libgcj.patch
 
 diff -ur libjava-orig/gnu/gcj/convert/natIconv.cc =
 libjava/gnu/gcj/convert/natIconv.cc=0A=
 --- libjava-orig/gnu/gcj/convert/natIconv.cc	Wed Nov  1 09:00:01 2000=0A=
 +++ libjava/gnu/gcj/convert/natIconv.cc	Wed Jul  4 21:29:52 2001=0A=
 @@ -11,12 +11,14 @@=0A=
  /* Author: Tom Tromey <tromey@redhat.com>.  */=0A=
  =0A=
  #include <config.h>=0A=
 +#include <errno.h>=0A=
  =0A=
  #include <gcj/cni.h>=0A=
  #include <jvm.h>=0A=
  =0A=
  #include <gnu/gcj/convert/Input_iconv.h>=0A=
  #include <gnu/gcj/convert/Output_iconv.h>=0A=
 +#include <java/io/CharConversionException.h>=0A=
  #include <java/io/UnsupportedEncodingException.h>=0A=
  =0A=
  #ifdef HAVE_ICONV=0A=
 @@ -84,7 +86,11 @@=0A=
    size_t r =3D iconv_adapter (iconv, (iconv_t) handle,=0A=
  			    &inbuf, &inavail,=0A=
  			    &outbuf, &outavail);=0A=
 -  // FIXME: what if R=3D=3D-1?=0A=
 +  if (r =3D=3D (size_t) -1) {=0A=
 +    if (errno =3D=3D EINVAL)	// incomplete character?=0A=
 +      return 0;=0A=
 +    throw new java::io::CharConversionException ();=0A=
 +  }=0A=
  =0A=
    if (iconv_byte_swap)=0A=
      {=0A=
 diff -ur libjava-orig/java/io/BufferedInputStream.java =
 libjava/java/io/BufferedInputStream.java=0A=
 --- libjava-orig/java/io/BufferedInputStream.java	Tue Mar  7 11:55:26 =
 2000=0A=
 +++ libjava/java/io/BufferedInputStream.java	Wed Jul  4 20:21:44 2001=0A=
 @@ -1,4 +1,4 @@=0A=
 -/* Copyright (C) 1998, 1999  Free Software Foundation=0A=
 +/* Copyright (C) 1998, 1999, 2001  Free Software Foundation=0A=
  =0A=
     This file is part of libgcj.=0A=
  =0A=
 @@ -131,7 +131,7 @@=0A=
      return origN - n;=0A=
    }=0A=
  =0A=
 -  private boolean refill() throws IOException=0A=
 +  boolean refill() throws IOException=0A=
    {=0A=
      if (markpos < 0)=0A=
        count =3D pos =3D 0;=0A=
 diff -ur libjava-orig/java/io/InputStreamReader.java =
 libjava/java/io/InputStreamReader.java=0A=
 --- libjava-orig/java/io/InputStreamReader.java	Thu Feb  8 17:54:38 2001=0A=
 +++ libjava/java/io/InputStreamReader.java	Wed Jul  4 22:08:03 2001=0A=
 @@ -44,13 +44,18 @@=0A=
  =0A=
    private InputStreamReader(InputStream in, BytesToUnicode decoder)=0A=
    {=0A=
 +    // FIXME: someone could pass in a BufferedInputStream whose buffer=0A=
 +    // is smaller than the longest encoded character for this=0A=
 +    // encoding.  We will probably go into an infinite loop in this=0A=
 +    // case.  We probably ought to just have our own byte buffering=0A=
 +    // here.=0A=
      this.in =3D in instanceof BufferedInputStream=0A=
                ? (BufferedInputStream) in=0A=
                : new BufferedInputStream(in);=0A=
      /* Don't need to call super(in) here as long as the lock gets set. =
 */=0A=
      this.lock =3D in;=0A=
      converter =3D decoder;=0A=
 -    converter.setInput(this.in.buf, 0, 0);=0A=
 +    work =3D new char [2048];=0A=
    }=0A=
  =0A=
    public void close() throws IOException=0A=
 @@ -76,28 +81,11 @@=0A=
  =0A=
  	if (wpos < wcount)=0A=
  	  return true;=0A=
 -	if (work =3D=3D null)=0A=
 -	  {=0A=
 -	    work =3D new char[100];=0A=
 -	    wpos =3D 0;=0A=
 -	    wcount =3D 0;=0A=
 -	  }=0A=
 -	for (;;)=0A=
 -	  {=0A=
 -	    if (in.available() <=3D 0)=0A=
 -	      return false;=0A=
 -	    in.mark(1);=0A=
 -	    int b =3D in.read();=0A=
 -	    if (b < 0)=0A=
 -	      return true;=0A=
 -	    in.reset();=0A=
 -	    converter.setInput(in.buf, in.pos, in.count);=0A=
 -	    wpos =3D 0;=0A=
 -	    wcount =3D converter.read(work, 0, work.length);=0A=
 -	    in.skip(converter.inpos - in.pos);=0A=
 -	    if (wcount > 0)=0A=
 -	      return true;=0A=
 -	  }=0A=
 +=0A=
 +	// According to the spec, an InputStreamReader is ready if its=0A=
 +	// input buffer is not empty (above), or if bytes are=0A=
 +	// available on the underlying byte stream.=0A=
 +	return in.available () > 0;=0A=
        }=0A=
    }=0A=
  =0A=
 @@ -108,33 +96,23 @@=0A=
  	if (in =3D=3D null)=0A=
  	  throw new IOException("Stream closed");=0A=
  =0A=
 +	if (length =3D=3D 0)=0A=
 +	  return 0;=0A=
 +=0A=
  	int wavail =3D wcount - wpos;=0A=
 -	if (wavail > 0)=0A=
 -	  {=0A=
 -	    if (length > wavail)=0A=
 -	      length =3D wavail;=0A=
 -	    System.arraycopy(work, wpos, buf, offset, length);=0A=
 -	    wpos +=3D length;=0A=
 -	    return length;=0A=
 -	  }=0A=
 -	else=0A=
 +	if (wavail <=3D 0)=0A=
  	  {=0A=
 -	    if (length =3D=3D 0)=0A=
 -	      return 0;=0A=
 -	    for (;;)=0A=
 -	      {=0A=
 -		in.mark(1);=0A=
 -		int b =3D in.read();=0A=
 -		if (b < 0)=0A=
 -		  return -1;=0A=
 -		in.reset();=0A=
 -		converter.setInput(in.buf, in.pos, in.count);=0A=
 -		int count =3D converter.read (buf, offset, length);=0A=
 -		in.skip(converter.inpos - in.pos);=0A=
 -		if (count > 0)=0A=
 -		  return count;=0A=
 -	      }=0A=
 +	    // Nothing waiting, so refill our buffer.=0A=
 +	    if (! refill ())=0A=
 +	      return -1;=0A=
 +	    wavail =3D wcount - wpos;=0A=
  	  }=0A=
 +=0A=
 +	if (length > wavail)=0A=
 +	  length =3D wavail;=0A=
 +	System.arraycopy(work, wpos, buf, offset, length);=0A=
 +	wpos +=3D length;=0A=
 +	return length;=0A=
        }=0A=
    }=0A=
  =0A=
 @@ -146,24 +124,39 @@=0A=
  	  throw new IOException("Stream closed");=0A=
  =0A=
  	int wavail =3D wcount - wpos;=0A=
 -	if (wavail > 0)=0A=
 -	  return work[wpos++];=0A=
 -	if (work =3D=3D null)=0A=
 +	if (wavail <=3D 0)=0A=
  	  {=0A=
 -	    work =3D new char[100];=0A=
 -	    wpos =3D 0;=0A=
 -	    wcount =3D 0;=0A=
 +	    // Nothing waiting, so refill our buffer.=0A=
 +	    if (! refill ())=0A=
 +	      return -1;=0A=
  	  }=0A=
 -	else if (wavail =3D=3D 0)=0A=
 +=0A=
 +	return work[wpos++];=0A=
 +      }=0A=
 +  }=0A=
 +=0A=
 +  // Read more bytes and convert them into the WORK buffer.=0A=
 +  // Return false on EOF.=0A=
 +  private boolean refill () throws IOException=0A=
 +  {=0A=
 +    wcount =3D wpos =3D 0;=0A=
 +    for (;;)=0A=
 +      {=0A=
 +	// We have knowledge of the internals of BufferedInputStream=0A=
 +	// here.  Eww.=0A=
 +	in.mark (0);=0A=
 +	boolean r =3D in.refill ();=0A=
 +	in.reset ();=0A=
 +	if (! r)=0A=
 +	  return false;=0A=
 +	converter.setInput(in.buf, in.pos, in.count);=0A=
 +	int count =3D converter.read (work, wpos, work.length - wpos);=0A=
 +	in.skip(converter.inpos - in.pos);=0A=
 +	if (count > 0)=0A=
  	  {=0A=
 -	    wpos =3D 0;=0A=
 -	    wcount =3D 0;=0A=
 +	    wcount +=3D count;=0A=
 +	    return true;=0A=
  	  }=0A=
 -	int count =3D read(work, wpos, work.length-wpos);=0A=
 -	if (count <=3D 0)=0A=
 -	  return -1;=0A=
 -	wcount =3D wpos + count;=0A=
 -	return work[wpos++];=0A=
        }=0A=
    }=0A=
  }=0A=
 
 --Boundary_(ID_byZdqokn58HeX4394FLC+Q)--


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-07-04 23:46 David Brownell
  0 siblings, 0 replies; 10+ messages in thread
From: David Brownell @ 2001-07-04 23:46 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: David Brownell <david-b@pacbell.net>
To: tromey@redhat.com
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: Wed, 04 Jul 2001 23:44:42 -0700

 > David> "FIXME:  what if R == -1 ?" comment which seems like it
 > David> is what's being hit here.
 > 
 > We definitely have to do something smarter if we hit an encoding
 > error.  Maybe throwing CharConversionException is appropriate?
 
 That'd be "r = -1" and "errno != EINVAL" ... EINVAL is
 the "not enough characters" case (not an "error"), the other
 documented cases would be real errors.
     
 > We currently don't throw that anywhere, which seems odd.
 > I think we ought to throw it if we detect garbage in the input
 > stream.  What do you think?
 
 Yes.  See the updated patch I'm sending in my next message.
 
 - Dave
 
 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-06-29 17:06 Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2001-06-29 17:06 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: Tom Tromey <tromey@redhat.com>
To: david-b@pacbell.net
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: 29 Jun 2001 18:20:47 -0600

 Hi David.  Could you try this untested patch and see if it helps this
 problem?
 
 If it doesn't work for you I will try to reproduce the failure myself
 and then I'll debug it for real.  I'll also do that if you can't test
 it.  (However, if I do have to do that it will have to be a lower
 priority...)
 
 2001-06-29  Tom Tromey  <tromey@redhat.com>
 
 	Fix for PR libgcj/3426:
 	* java/io/BufferedInputStream.java (refill): Now package-private.
 	* java/io/InputStreamReader.java (ready): Simplified.
 	(refill): New method.
 	(read): Use it.
 
 Tom
 
 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
 --- BufferedInputStream.java	2000/03/07 19:55:26	1.3
 +++ BufferedInputStream.java	2001/06/29 23:56:54
 @@ -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
 --- InputStreamReader.java	2001/02/09 01:54:38	1.8
 +++ InputStreamReader.java	2001/06/29 23:56:54
 @@ -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,39 @@
  	  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;
 +    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++];
        }
    }
  }


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-06-29 16:26 Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2001-06-29 16:26 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: Tom Tromey <tromey@redhat.com>
To: david-b@pacbell.net
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: 29 Jun 2001 16:57:54 -0600

 >>>>> "David" == david-b  <david-b@pacbell.net> writes:
 
 David> The for(;;) loop in the second half of
 David> java.io.InputStreamReader will loop infinitely in the following
 David> case:
 
 I looked at this and I agree.  The problem is that the
 InputStreamReader has no way to force the BufferedInputStream to
 refill its buffer.  So in your scenario, instead of making progress
 we simply keep trying the same thing over and over.
 
 One fix might be to make BufferedInputStream.refill package-private
 and then call it from InputStreamReader.read while the mark is set.
 This is pretty ugly.  It is hard to see what else we could do
 without rewriting InputStreamReader.  I'd prefer not to do that,
 I think.
 
 David> "FIXME:  what if R == -1 ?" comment which seems like it
 David> is what's being hit here.
 
 We definitely have to do something smarter if we hit an encoding
 error.  Maybe throwing CharConversionException is appropriate?
 We currently don't throw that anywhere, which seems odd.
 I think we ought to throw it if we detect garbage in the input
 stream.  What do you think?
 
 Tom


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: java/3426: java.io.InputStreamReader, infinite loop
@ 2001-06-29 15:46 Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2001-06-29 15:46 UTC (permalink / raw)
  To: nobody; +Cc: gcc-prs

The following reply was made to PR libgcj/3426; it has been noted by GNATS.

From: Tom Tromey <tromey@redhat.com>
To: david-b@pacbell.net
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: java/3426: java.io.InputStreamReader, infinite loop
Date: 29 Jun 2001 16:57:54 -0600

 >>>>> "David" == david-b  <david-b@pacbell.net> writes:
 
 David> The for(;;) loop in the second half of
 David> java.io.InputStreamReader will loop infinitely in the following
 David> case:
 
 I looked at this and I agree.  The problem is that the
 InputStreamReader has no way to force the BufferedInputStream to
 refill its buffer.  So in your scenario, instead of making progress
 we simply keep trying the same thing over and over.
 
 One fix might be to make BufferedInputStream.refill package-private
 and then call it from InputStreamReader.read while the mark is set.
 This is pretty ugly.  It is hard to see what else we could do
 without rewriting InputStreamReader.  I'd prefer not to do that,
 I think.
 
 David> "FIXME:  what if R == -1 ?" comment which seems like it
 David> is what's being hit here.
 
 We definitely have to do something smarter if we hit an encoding
 error.  Maybe throwing CharConversionException is appropriate?
 We currently don't throw that anywhere, which seems odd.
 I think we ought to throw it if we detect garbage in the input
 stream.  What do you think?
 
 Tom


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2001-07-12 22:56 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-06-26  8:16 java/3426: java.io.InputStreamReader, infinite loop david-b
2001-06-29 15:46 Tom Tromey
2001-06-29 16:26 Tom Tromey
2001-06-29 17:06 Tom Tromey
2001-07-04 23:46 David Brownell
2001-07-04 23:56 David Brownell
2001-07-12 21:36 Tom Tromey
2001-07-12 22:36 Tom Tromey
2001-07-12 22:36 Tom Tromey
2001-07-12 22:56 David Brownell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).