From 1139a7354d6818da06edf5227ef6c12c08289b91 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Mon, 28 Feb 2011 23:50:57 +0000 Subject: [PATCH] re PR libstdc++/47921 (pbump will overflow when input n is larger than 2G-1) 2011-02-28 Paolo Carlini PR libstdc++/47921 * include/std/streambuf (basic_streambuf<>::__safe_gbump, __safe_pbump): Add. * include/bits/streambuf.tcc (basic_streambuf<>::xgetn, xputn): Use the latter. * include/bits/streambuf_iterator.h: Likewise. * src/strstream.cc: Likewise. * src/streambuf.cc: Likewise. * src/compatibility.cc: Likewise. * src/istream.cc: Likewise. * include/bits/fstream.tcc (basic_filebuf<>::xsgetn): Use setg instead of gbump. * include/std/sstream (basic_stringbuf<>::_M_pbump): Add. * include/bits/sstream.tcc (basic_stringbuf<>::seekoff, seekpos, _M_sync): Use setg, setp, and _M_pbump. * config/abi/pre/gnu.ver: Tweak. From-SVN: r170579 --- libstdc++-v3/ChangeLog | 19 ++++++++++++ libstdc++-v3/config/abi/pre/gnu.ver | 3 +- libstdc++-v3/include/bits/fstream.tcc | 12 ++++---- libstdc++-v3/include/bits/sstream.tcc | 29 ++++++++++++++----- libstdc++-v3/include/bits/streambuf.tcc | 6 ++-- .../include/bits/streambuf_iterator.h | 6 ++-- libstdc++-v3/include/std/sstream | 5 ++++ libstdc++-v3/include/std/streambuf | 7 +++++ libstdc++-v3/src/compatibility.cc | 4 +-- libstdc++-v3/src/istream.cc | 16 +++++----- libstdc++-v3/src/streambuf.cc | 7 +++-- libstdc++-v3/src/strstream.cc | 9 +++--- 12 files changed, 85 insertions(+), 38 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 91706ad8a6c1..16ee72899920 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2011-02-28 Paolo Carlini + + PR libstdc++/47921 + * include/std/streambuf (basic_streambuf<>::__safe_gbump, + __safe_pbump): Add. + * include/bits/streambuf.tcc (basic_streambuf<>::xgetn, + xputn): Use the latter. + * include/bits/streambuf_iterator.h: Likewise. + * src/strstream.cc: Likewise. + * src/streambuf.cc: Likewise. + * src/compatibility.cc: Likewise. + * src/istream.cc: Likewise. + * include/bits/fstream.tcc (basic_filebuf<>::xsgetn): Use setg + instead of gbump. + * include/std/sstream (basic_stringbuf<>::_M_pbump): Add. + * include/bits/sstream.tcc (basic_stringbuf<>::seekoff, + seekpos, _M_sync): Use setg, setp, and _M_pbump. + * config/abi/pre/gnu.ver: Tweak. + 2011-02-28 Paolo Carlini * testsuite/20_util/ratio/comparisons/comp3.cc: New. diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index aa4031afade3..b3e5380f76da 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -322,7 +322,8 @@ GLIBCXX_3.4 { _ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEE3strERKSs; _ZNSt15basic_stringbufIwSt11char_traitsIwESaIwEE3strERKSbIwS1_S2_E; _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9][t-z]*; - _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9]_M_[a-z]*; + _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9]_M_[a-o]*; + _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9]_M_[q-z]*; _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9][0-9]_M_[a-z]*; # std::basic_iostream constructors, destructors diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index edaff970374a..282934e0b531 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -584,14 +584,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const streamsize __avail = this->egptr() - this->gptr(); if (__avail != 0) { - if (__avail == 1) - *__s = *this->gptr(); - else - traits_type::copy(__s, this->gptr(), __avail); + traits_type::copy(__s, this->gptr(), __avail); __s += __avail; - this->gbump(__avail); - __ret += __avail; - __n -= __avail; + this->setg(this->eback(), this->gptr() + __avail, + this->egptr()); + __ret += __avail; + __n -= __avail; } // Need to loop in case of short reads (relatively common diff --git a/libstdc++-v3/include/bits/sstream.tcc b/libstdc++-v3/include/bits/sstream.tcc index 8956e9ee7586..ffa92e73baa0 100644 --- a/libstdc++-v3/include/bits/sstream.tcc +++ b/libstdc++-v3/include/bits/sstream.tcc @@ -1,7 +1,7 @@ // String based streams -*- C++ -*- // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2007, 2009, 2010 +// 2006, 2007, 2008, 2009, 2010, 2011 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -178,14 +178,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && __newoffi >= 0 && this->egptr() - __beg >= __newoffi) { - this->gbump((__beg + __newoffi) - this->gptr()); + this->setg(this->eback(), this->eback() + __newoffi, + this->egptr()); __ret = pos_type(__newoffi); } if ((__testout || __testboth) && __newoffo >= 0 && this->egptr() - __beg >= __newoffo) { - this->pbump((__beg + __newoffo) - this->pptr()); + _M_pbump(this->pbase(), this->epptr(), __newoffo); __ret = pos_type(__newoffo); } } @@ -212,9 +213,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__testpos) { if (__testin) - this->gbump((__beg + __pos) - this->gptr()); + this->setg(this->eback(), this->eback() + __pos, + this->egptr()); if (__testout) - this->pbump((__beg + __pos) - this->pptr()); + _M_pbump(this->pbase(), this->epptr(), __pos); __ret = __sp; } } @@ -243,8 +245,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION this->setg(__base, __base + __i, __endg); if (__testout) { - this->setp(__base, __endp); - this->pbump(__o); + _M_pbump(__base, __endp, __o); // egptr() always tracks the string end. When !__testin, // for the correct functioning of the streambuf inlines // the other get area pointers are identical. @@ -253,6 +254,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + template + void + basic_stringbuf<_CharT, _Traits, _Alloc>:: + _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off) + { + this->setp(__pbeg, __pend); + while (__off > __gnu_cxx::__numeric_traits::__max) + { + this->pbump(__gnu_cxx::__numeric_traits::__max); + __off -= __gnu_cxx::__numeric_traits::__max; + } + this->pbump(__off); + } + // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. diff --git a/libstdc++-v3/include/bits/streambuf.tcc b/libstdc++-v3/include/bits/streambuf.tcc index 253f308dc88b..d154ef1f19a4 100644 --- a/libstdc++-v3/include/bits/streambuf.tcc +++ b/libstdc++-v3/include/bits/streambuf.tcc @@ -1,7 +1,7 @@ // Stream buffer classes -*- C++ -*- // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2009, 2010 Free Software Foundation, Inc. +// 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -57,7 +57,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION traits_type::copy(__s, this->gptr(), __len); __ret += __len; __s += __len; - this->gbump(__len); + this->__safe_gbump(__len); } if (__ret < __n) @@ -91,7 +91,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION traits_type::copy(this->pptr(), __s, __len); __ret += __len; __s += __len; - this->pbump(__len); + this->__safe_pbump(__len); } if (__ret < __n) diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index 6032a29e6f80..83ae6785c2d0 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -1,7 +1,7 @@ // Streambuf iterators // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2007, 2009, 2010 +// 2006, 2007, 2009, 2010, 2011 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -339,7 +339,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > 1) { traits_type::copy(__result, __sb->gptr(), __n); - __sb->gbump(__n); + __sb->__safe_gbump(__n); __result += __n; __c = __sb->underflow(); } @@ -379,7 +379,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __n, __val); if (__p) __n = __p - __sb->gptr(); - __sb->gbump(__n); + __sb->__safe_gbump(__n); __c = __sb->sgetc(); } else diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream index 6dd0a3d8f56e..bf2862add30a 100644 --- a/libstdc++-v3/include/std/sstream +++ b/libstdc++-v3/include/std/sstream @@ -241,6 +241,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION this->setg(this->pptr(), this->pptr(), this->pptr()); } } + + // Works around the issue with pbump, part of the protected + // interface of basic_streambuf, taking just an int. + void + _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off); }; diff --git a/libstdc++-v3/include/std/streambuf b/libstdc++-v3/include/std/streambuf index 0121ac2de988..b46efec46010 100644 --- a/libstdc++-v3/include/std/streambuf +++ b/libstdc++-v3/include/std/streambuf @@ -769,6 +769,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif + // Also used by specializations for char and wchar_t in src. + void + __safe_gbump(streamsize __n) { _M_in_cur += __n; } + + void + __safe_pbump(streamsize __n) { _M_out_cur += __n; } + private: // _GLIBCXX_RESOLVE_LIB_DEFECTS // Side effect of DR 50. diff --git a/libstdc++-v3/src/compatibility.cc b/libstdc++-v3/src/compatibility.cc index d5d39b3317af..d4cf5d7c1225 100644 --- a/libstdc++-v3/src/compatibility.cc +++ b/libstdc++-v3/src/compatibility.cc @@ -86,7 +86,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION streamsize(__n - _M_gcount)); if (__size > 1) { - __sb->gbump(__size); + __sb->__safe_gbump(__size); _M_gcount += __size; __c = __sb->sgetc(); } @@ -157,7 +157,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION streamsize(__n - _M_gcount)); if (__size > 1) { - __sb->gbump(__size); + __sb->__safe_gbump(__size); _M_gcount += __size; __c = __sb->sgetc(); } diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc index e550306a0e69..f161016cf3d1 100644 --- a/libstdc++-v3/src/istream.cc +++ b/libstdc++-v3/src/istream.cc @@ -67,7 +67,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __size = __p - __sb->gptr(); traits_type::copy(__s, __sb->gptr(), __size); __s += __size; - __sb->gbump(__size); + __sb->__safe_gbump(__size); _M_gcount += __size; __c = __sb->sgetc(); } @@ -145,7 +145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cdelim); if (__p) __size = __p - __sb->gptr(); - __sb->gbump(__size); + __sb->__safe_gbump(__size); _M_gcount += __size; __c = __sb->sgetc(); } @@ -239,7 +239,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION - __sb->gptr()); __traits_type::copy(__s, __sb->gptr(), __size); __s += __size; - __sb->gbump(__size); + __sb->__safe_gbump(__size); __extracted += __size; __c = __sb->sgetc(); } @@ -318,7 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __sb->gptr() + __size) - __sb->gptr()); __str.append(__sb->gptr(), __size); - __sb->gbump(__size); + __sb->__safe_gbump(__size); __extracted += __size; __c = __sb->sgetc(); } @@ -397,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__p) __size = __p - __sb->gptr(); __str.append(__sb->gptr(), __size); - __sb->gbump(__size); + __sb->__safe_gbump(__size); __extracted += __size; __c = __sb->sgetc(); } @@ -474,7 +474,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __size = __p - __sb->gptr(); traits_type::copy(__s, __sb->gptr(), __size); __s += __size; - __sb->gbump(__size); + __sb->__safe_gbump(__size); _M_gcount += __size; __c = __sb->sgetc(); } @@ -552,7 +552,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cdelim); if (__p) __size = __p - __sb->gptr(); - __sb->gbump(__size); + __sb->__safe_gbump(__size); _M_gcount += __size; __c = __sb->sgetc(); } @@ -643,7 +643,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__p) __size = __p - __sb->gptr(); __str.append(__sb->gptr(), __size); - __sb->gbump(__size); + __sb->__safe_gbump(__size); __extracted += __size; __c = __sb->sgetc(); } diff --git a/libstdc++-v3/src/streambuf.cc b/libstdc++-v3/src/streambuf.cc index 2e72559d827d..5bcd0ea8d585 100644 --- a/libstdc++-v3/src/streambuf.cc +++ b/libstdc++-v3/src/streambuf.cc @@ -1,6 +1,7 @@ // Stream buffer classes -*- C++ -*- -// Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc. +// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +// Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -47,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > 1) { const streamsize __wrote = __sbout->sputn(__sbin->gptr(), __n); - __sbin->gbump(__wrote); + __sbin->__safe_gbump(__wrote); __ret += __wrote; if (__wrote < __n) { @@ -87,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > 1) { const streamsize __wrote = __sbout->sputn(__sbin->gptr(), __n); - __sbin->gbump(__wrote); + __sbin->__safe_gbump(__wrote); __ret += __wrote; if (__wrote < __n) { diff --git a/libstdc++-v3/src/strstream.cc b/libstdc++-v3/src/strstream.cc index d6c936e5f9df..c76fc60e0ac5 100644 --- a/libstdc++-v3/src/strstream.cc +++ b/libstdc++-v3/src/strstream.cc @@ -1,6 +1,7 @@ // strstream definitions -*- C++ -*- -// Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation +// Copyright (C) 2001, 2002, 2003, 2005, 2009, 2010, 2011 +// Free Software Foundation // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -161,7 +162,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } setp(buf, buf + new_size); - pbump(old_size); + __safe_pbump(old_size); if (reposition_get) setg(buf, buf + old_get_offset, buf + @@ -271,12 +272,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (seeklow + off < pbase()) { setp(seeklow, epptr()); - pbump(off); + __safe_pbump(off); } else { setp(pbase(), epptr()); - pbump(off - (pbase() - seeklow)); + __safe_pbump(off - (pbase() - seeklow)); } } if (do_get) -- 2.39.2