Bug 8071

Summary: basic_ostream::operator<<(streambuf*) loops forever if streambuf::underflow() leaves gptr() NULL
Product: gcc Reporter: Jonathan Lennox <lennox>
Component: libstdc++Assignee: Benjamin Kosnik <bkoz>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs, lennox
Priority: P3    
Version: 3.1   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:
Attachments: syncstream.h

Description Jonathan Lennox 2002-09-27 08:56:01 UTC
According to my reading of the C++ standard, a subclass of std::basic_streambuf<> is allowed to declare its uflow() and underflow() functions such that they don't fill their buffers.  This is useful, for instance, if the streambuf is a wrapper around another type that does its own buffering.

However, libstdc++'s basic_ostream::operator<<(streambuf*) operator loops forever when passed such a streambuf, repeatedly invoking underflow() and never actually extracting any data from the buffer.

I've attached some code written by Matt Austern, and published in the C++ Users Journal.  This code creates a streambuf and istream that wraps a C FILE*, so I/O can safely be intermixed on the two types.  Using operator<< on the syncbuf this code declares illustrates the problem.

Release:
gcc-3.1

Environment:
sparc-sun-solaris2.8

How-To-Repeat:
Compile the attached code.  (It looks like gnats won't allow me to attach more than one file in the initial bug report, so I've just attached the header.  I'll attach the body momentarily.)
Comment 1 Jonathan Lennox 2002-09-27 08:56:01 UTC
Fix:
I think the fix needs to change basic_streambuf::__copy_streambufs, but I'm not sure exactly what the fix should be.
Comment 2 Jonathan Lennox 2002-09-27 12:10:26 UTC
From: Jonathan Lennox <lennox@cs.columbia.edu>
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: libstdc++/8071: basic_ostream::operator<<(streambuf*) loops forever if streambuf::underflow() leaves gptr() NULL
Date: Fri, 27 Sep 2002 12:10:26 -0400

 --prVVYBvZNE
 Content-Type: text/plain; charset=us-ascii
 Content-Description: message body text
 Content-Transfer-Encoding: 7bit
 
 Here is the additional code, which uses the header file previously
 attached.
 
 
 --prVVYBvZNE
 Content-Type: text/plain
 Content-Disposition: inline;
 	filename="test-syncstream.cxx"
 Content-Transfer-Encoding: 7bit
 
 #include "syncstream.h"
 
 using namespace std;
 
 int main(int argc, char *argv[]) 
 {
   if (argc < 2) {
     cerr << "Usage: " << argv[0] << " [file]" << endl;
     exit(2);
   }
   FILE* c_file = fopen(argv[1], "r");
 
   if (c_file == NULL) {
     perror(argv[1]);
     exit(1);
   }
 
   isyncstream cxx_file(c_file);
 
   cout << cxx_file.rdbuf();
 
   exit(0);
 }
 
 --prVVYBvZNE--

Comment 3 Benjamin Kosnik 2002-10-09 06:32:12 UTC
From: bkoz@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: libstdc++/8071
Date: 9 Oct 2002 06:32:12 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Changes by:	bkoz@gcc.gnu.org	2002-10-08 23:32:12
 
 Modified files:
 	libstdc++-v3   : ChangeLog 
 	libstdc++-v3/include/bits: streambuf.tcc 
 	libstdc++-v3/testsuite/27_io: ostream_inserter_other.cc 
 
 Log message:
 	2002-10-08  Jonathan Lennox  <lennox@cs.columbia.edu>
 	
 	PR libstdc++/8071, libstdc++/8127, c++/6745
 	* streambuf.tcc (__copy_streambufs): Handle cases where
 	__sbin->in_avail() returns 0, or where __sbin doesn't set gptr().
 	* testsuite/27_io/ostream_inserter_other.cc (test05): Add.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&r1=1.1377&r2=1.1378
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/bits/streambuf.tcc.diff?cvsroot=gcc&r1=1.15&r2=1.16
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/testsuite/27_io/ostream_inserter_other.cc.diff?cvsroot=gcc&r1=1.11&r2=1.12
 

Comment 4 Benjamin Kosnik 2002-10-11 08:15:59 UTC
From: bkoz@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: libstdc++/8071
Date: 11 Oct 2002 08:15:59 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Branch: 	gcc-3_2-branch
 Changes by:	bkoz@gcc.gnu.org	2002-10-11 01:15:58
 
 Modified files:
 	libstdc++-v3   : ChangeLog 
 	libstdc++-v3/include/bits: streambuf.tcc 
 	libstdc++-v3/testsuite/27_io: ostream_inserter_other.cc 
 
 Log message:
 	2002-10-10  Jonathan Lennox  <lennox@cs.columbia.edu>
 	
 	PR libstdc++/8071, libstdc++/8127, c++/6745
 	* streambuf.tcc (__copy_streambufs): Handle cases where
 	__sbin->in_avail() returns 0, or where __sbin doesn't set gptr().
 	* testsuite/27_io/ostream_inserter_other.cc (test05): Add.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1057.2.159.2.32&r2=1.1057.2.159.2.33
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/bits/streambuf.tcc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.12.2.2.4.1&r2=1.12.2.2.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/testsuite/27_io/ostream_inserter_other.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.10.2.1&r2=1.10.2.1.2.1
 
Comment 5 Benjamin Kosnik 2002-10-20 09:32:46 UTC
Responsible-Changed-From-To: unassigned->bkoz
Responsible-Changed-Why: Mine.
Comment 6 Benjamin Kosnik 2002-10-20 09:32:46 UTC
State-Changed-From-To: open->feedback
State-Changed-Why: I think this is fixed.
Comment 7 Benjamin Kosnik 2002-11-06 08:47:06 UTC
State-Changed-From-To: feedback->closed
State-Changed-Why: Fixed.