re PR libstdc++/47921 (pbump will overflow when input n is larger than 2G-1)
authorPaolo Carlini <paolo.carlini@oracle.com>
Mon, 28 Feb 2011 23:50:57 +0000 (23:50 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 28 Feb 2011 23:50:57 +0000 (23:50 +0000)
2011-02-28  Paolo Carlini  <paolo.carlini@oracle.com>

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

12 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/bits/sstream.tcc
libstdc++-v3/include/bits/streambuf.tcc
libstdc++-v3/include/bits/streambuf_iterator.h
libstdc++-v3/include/std/sstream
libstdc++-v3/include/std/streambuf
libstdc++-v3/src/compatibility.cc
libstdc++-v3/src/istream.cc
libstdc++-v3/src/streambuf.cc
libstdc++-v3/src/strstream.cc

index 91706ad8a6c1c4d9dc17f5851ef6503d98e064fa..16ee72899920a0e66aa683cb1dff1bbff93ac2ef 100644 (file)
@@ -1,3 +1,22 @@
+2011-02-28  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       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  <paolo.carlini@oracle.com>
 
        * testsuite/20_util/ratio/comparisons/comp3.cc: New.
index aa4031afade313857ee29cb85868585d14ca72fe..b3e5380f76dad8fabcd77b8ea17649309ff086af 100644 (file)
@@ -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
index edaff970374ae6a43a997a3358e4dd06f87fe1d5..282934e0b531e0096a7223fa67b5889bad1190a8 100644 (file)
@@ -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
index 8956e9ee758626f5990695122321dbac80842ab3..ffa92e73baa021c0206af10a3b3a0893f989d002 100644 (file)
@@ -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 <class _CharT, class _Traits, class _Alloc>
+    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<int>::__max)
+       {
+         this->pbump(__gnu_cxx::__numeric_traits<int>::__max);
+         __off -= __gnu_cxx::__numeric_traits<int>::__max;
+       }
+      this->pbump(__off);
+    }
+
   // Inhibit implicit instantiations for required instantiations,
   // which are defined via explicit instantiations elsewhere.
   // NB:  This syntax is a GNU extension.
index 253f308dc88bd6ea85c94f325bcacfcabd38fda3..d154ef1f19a47ec40757236ae1448740e66208e0 100644 (file)
@@ -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)
index 6032a29e6f80c54bef6879347083fe4bf5d1e223..83ae6785c2d069c50968ac47fc7d1ff7de91cedf 100644 (file)
@@ -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
index 6dd0a3d8f56e6d40c234defa29027b70dab086bb..bf2862add30aeddc6641b7937741077af8597ae7 100644 (file)
@@ -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);
     };
 
 
index 0121ac2de9884c9979907193bbd99a7d6cf46d8e..b46efec460106b98492c3e2d2eb898cb8f80be9b 100644 (file)
@@ -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. 
index d5d39b3317afc52b5e06ff3573c571400b5cf647..d4cf5d7c1225543d72705a9dd376136ce965bf31 100644 (file)
@@ -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();
                        }
index e550306a0e69d7f45b2bd00561e275a56d9b95bd..f161016cf3d1dcd0a5e4f53df57d8d92fd39a98f 100644 (file)
@@ -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();
                    }
index 2e72559d827da9e055a24bba198878e7c7983d23..5bcd0ea8d58516807ecf9e5ccfbe70e925eb4ec6 100644 (file)
@@ -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)
                {
index d6c936e5f9df8a9c9e134478ed379becae4fc7b9..c76fc60e0ac57bbfe251feac1464eb3d5f095fa6 100644 (file)
@@ -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)