This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [Patch] Fix libstdc++/9182
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: Pétur Runólfsson <peturr02 at ru dot is>
- Cc: libstdc++ at gcc dot gnu dot org, bkoz <bkoz at redhat dot com>
- Date: Sun, 02 Mar 2003 13:39:57 +0100
- Subject: Re: [Patch] Fix libstdc++/9182
- References: <07D05A69A3D0C14FAEA60C3ACE8E5564028F5537@nike.hir.is>
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;
}