This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch] Fix libstdc++/9182


Pétur Runólfsson wrote:

Does this handle the case when the first call to __cvt.out() in
_M_convert_to_external returns partial and the second call returns
error?

The below deals with this corner case too: _M_convert_to external has
to be modified to set __elen = 0 in that case.

In fact, I have to thank you, since in this way, the value of checking
for __elen in two different places in _M_really_overflow is increased.

Paolo.

//////////
2003-03-02  Paolo Carlini  <pcarlini at unitus dot it>

	PR libstdc++/9182
	* include/bits/fstream.tcc (_M_really_overflow): Check
	for _M_convert_to_external possible failures.
	* include/std/std_fstream.h (sync): Check _M_really_overflow
	return value and return -1 in case of failure.
	* testsuite/27_io/filebuf_virtuals.cc (test13, test14): Add.

	* include/bits/fstream.tcc (_M_convert_to_external):
	Set __elen to zero if codecvt::out eventually fails.
diff -prN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
*** libstdc++-v3-orig/include/bits/fstream.tcc	Sun Feb 23 00:09:01 2003
--- libstdc++-v3/include/bits/fstream.tcc	Sun Mar  2 13:21:05 2003
*************** namespace std
*** 320,327 ****
  			      __iend, __buf, __buf + __blen, __bend);
  	      if (__r != codecvt_base::error)
  		__rlen = __bend - __buf;
! 	      else 
! 		__rlen = 0;
  	      if (__rlen)
  		{
  		  __elen += _M_file.xsputn(__buf, __rlen);
--- 320,332 ----
  			      __iend, __buf, __buf + __blen, __bend);
  	      if (__r != codecvt_base::error)
  		__rlen = __bend - __buf;
! 	      else
! 		{
! 		  __rlen = 0;
! 		  // Signal to the caller (_M_really_overflow) that
! 		  // codecvt::out eventually failed.
! 		  __elen = 0;
! 		}
  	      if (__rlen)
  		{
  		  __elen += _M_file.xsputn(__buf, __rlen);
*************** namespace std
*** 362,387 ****
  				   this->_M_out_lim - this->_M_out_beg, 
  				   __elen, __plen);
  
! 	  // Convert pending sequence to external representation, output.
! 	  // If eof, then just attempt sync.
! 	  if (!traits_type::eq_int_type(__c, traits_type::eof()))
  	    {
! 	      char_type __pending = traits_type::to_char_type(__c);
! 	      _M_convert_to_external(&__pending, 1, __elen, __plen);
  
! 	      // User code must flush when switching modes (thus don't sync).
! 	      if (__elen == __plen)
  		{
  		  _M_set_indeterminate();
  		  __ret = traits_type::not_eof(__c);
  		}
  	    }
! 	  else if (!_M_file.sync())
! 	    {
! 	      _M_set_indeterminate();
! 	      __ret = traits_type::not_eof(__c);
! 	    }
! 	}	      
        _M_last_overflowed = true;	
        return __ret;
      }
--- 367,397 ----
  				   this->_M_out_lim - this->_M_out_beg, 
  				   __elen, __plen);
  
! 	  // Checks for codecvt.out failures and _M_file.xsputn failures,
! 	  // respectively, inside _M_convert_to_external.
! 	  if (__testunbuffered || (__elen && __elen == __plen))
  	    {
! 	      // Convert pending sequence to external representation, output.
! 	      // If eof, then just attempt sync.
! 	      if (!traits_type::eq_int_type(__c, traits_type::eof()))
! 		{
! 		  char_type __pending = traits_type::to_char_type(__c);
! 		  _M_convert_to_external(&__pending, 1, __elen, __plen);
  
! 		  // User code must flush when switching modes (thus don't sync).
! 		  if (__elen == __plen && __elen)
! 		    {
! 		      _M_set_indeterminate();
! 		      __ret = traits_type::not_eof(__c);
! 		    }
! 		}
! 	      else if (!_M_file.sync())
  		{
  		  _M_set_indeterminate();
  		  __ret = traits_type::not_eof(__c);
  		}
  	    }
! 	}
        _M_last_overflowed = true;	
        return __ret;
      }
diff -prN libstdc++-v3-orig/include/std/std_fstream.h libstdc++-v3/include/std/std_fstream.h
*** libstdc++-v3-orig/include/std/std_fstream.h	Sat Feb 22 17:16:49 2003
--- libstdc++-v3/include/std/std_fstream.h	Sat Mar  1 21:02:25 2003
*************** namespace std
*** 311,316 ****
--- 311,317 ----
        virtual int
        sync()
        {
+ 	int __ret = 0;
  	bool __testput = this->_M_out_cur
  	  && this->_M_out_beg < this->_M_out_lim;
  
*************** namespace std
*** 320,333 ****
  	  {
  	    // Need to restore current position after the write.
  	    off_type __off = this->_M_out_cur - this->_M_out_lim;
! 	    _M_really_overflow(); // _M_file.sync() will be called within
! 	    if (__off)
  	      _M_file.seekoff(__off, ios_base::cur);
  	  }
  	else
  	  _M_file.sync();
  	_M_last_overflowed = false;
! 	return 0;
        }
  
        // [documentation is inherited]
--- 321,339 ----
  	  {
  	    // Need to restore current position after the write.
  	    off_type __off = this->_M_out_cur - this->_M_out_lim;
! 
! 	    // _M_file.sync() will be called within
! 	    if (traits_type::eq_int_type(_M_really_overflow(),
! 					 traits_type::eof()))
! 	      __ret = -1;
! 	    else if (__off)
  	      _M_file.seekoff(__off, ios_base::cur);
  	  }
  	else
  	  _M_file.sync();
+ 
  	_M_last_overflowed = false;
! 	return __ret;
        }
  
        // [documentation is inherited]
diff -prN libstdc++-v3-orig/testsuite/27_io/filebuf_virtuals.cc libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc
*** libstdc++-v3-orig/testsuite/27_io/filebuf_virtuals.cc	Mon Feb 24 20:20:24 2003
--- libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc	Sat Mar  1 20:34:51 2003
*************** const char name_03[] = "filebuf_virtuals
*** 74,79 ****
--- 74,80 ----
  const char name_04[] = "filebuf_virtuals-4.txt"; // empty file, need to create
  const char name_05[] = "filebuf_virtuals-5.txt"; // empty file, need to create
  const char name_06[] = "filebuf_virtuals-6.txt"; // empty file, need to create
+ const char name_07[] = "filebuf_virtuals-7.txt"; // empty file, need to create
  
  class derived_filebuf: public std::filebuf
  {
*************** void test12()
*** 704,709 ****
--- 705,764 ----
    fbuf.close();  
  }
  
+ class errorcvt : public std::codecvt<char, char, mbstate_t>
+ {
+ protected:
+   std::codecvt_base::result
+   do_out(mbstate_t&, const char* from, const char*,
+ 	 const char*& from_next, char* to, char*,
+ 	 char*& to_next) const
+   {
+     from_next = from;
+     to_next = to;
+     return std::codecvt<char, char, mbstate_t>::error;
+   }
+   
+   virtual bool do_always_noconv() const throw()
+   {
+     return false;
+   }
+ };
+ 
+ // libstdc++/9182
+ void test13()
+ {
+   using namespace std;
+   bool test = true;
+ 
+   locale loc;
+   loc = locale(loc, new errorcvt);
+   
+   filebuf fbuf1;
+   fbuf1.pubimbue(loc);
+   fbuf1.open(name_07, ios_base::out | ios_base::trunc);
+   fbuf1.sputn("ison", 4); 
+   int r = fbuf1.pubsync();
+   VERIFY( r == -1 );
+   fbuf1.close();
+ }
+ 
+ void test14()
+ {
+   using namespace std;
+   bool test = true;
+   
+   locale loc;
+   loc = locale(loc, new errorcvt);
+   
+   filebuf fbuf1;
+   fbuf1.pubimbue(loc);
+   fbuf1.pubsetbuf(0, 0);
+   fbuf1.open(name_07, ios_base::out | ios_base::trunc);
+   streamsize n = fbuf1.sputn("onne", 4);
+   VERIFY( n == 0 );
+   fbuf1.close();
+ }
+ 
  main() 
  {
    test01();
*************** main() 
*** 720,724 ****
--- 775,781 ----
    test10();
    test11();
    test12();
+   test13();
+   test14();
    return 0;
  }

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