This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3] Avoid overflowing stringbuf::setbuf buffers
- From: Paolo Carlini <pcarlini at suse dot de>
- To: "'gcc-patches at gcc dot gnu dot org'" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 06 Oct 2004 11:11:51 +0200
- Subject: [v3] Avoid overflowing stringbuf::setbuf buffers
Hi,
tested x86/x86_64-linux, committed to mainline.
Paolo.
/////////////
2004-10-06 Paolo Carlini <pcarlini@suse.de>
* include/std/std_sstream.h (_M_sync): When the caller is
setbuf, don't trust _M_string.capacity() to be the size of
the buffer area, use _M_string.size() in this case.
* testsuite/27_io/basic_stringbuf/setbuf/char/4.cc: New.
* testsuite/27_io/basic_stringbuf/setbuf/wchar_t/4.cc: Likewise.
* include/bits/sstream.tcc (overflow): Avoid calling string::assign
unnecessarily when the current _M_string is empty.
diff -urN libstdc++-v3-orig/include/bits/sstream.tcc libstdc++-v3/include/bits/sstream.tcc
--- libstdc++-v3-orig/include/bits/sstream.tcc 2004-10-03 13:33:53.000000000 +0200
+++ libstdc++-v3/include/bits/sstream.tcc 2004-10-05 15:36:12.000000000 +0200
@@ -109,7 +109,8 @@
const __size_type __len = std::min(__opt_len, __max_size);
__string_type __tmp;
__tmp.reserve(__len);
- __tmp.assign(_M_string.data(), this->epptr() - this->pbase());
+ if (this->pbase())
+ __tmp.assign(this->pbase(), this->epptr() - this->pbase());
_M_string.swap(__tmp);
_M_sync(const_cast<char_type*>(_M_string.data()),
this->gptr() - this->eback(), this->pptr() - this->pbase());
diff -urN libstdc++-v3-orig/include/std/std_sstream.h libstdc++-v3/include/std/std_sstream.h
--- libstdc++-v3-orig/include/std/std_sstream.h 2004-10-01 11:22:49.000000000 +0200
+++ libstdc++-v3/include/std/std_sstream.h 2004-10-05 18:24:24.000000000 +0200
@@ -259,7 +259,13 @@
this->setg(__base, __base + __i, __end);
if (__testout)
{
- this->setp(__base, __base + _M_string.capacity());
+ // If __base comes from setbuf we cannot trust capacity()
+ // to match the size of the buffer area: in general, after
+ // Step 1 above, _M_string.capacity() >= __n.
+ if (__base == _M_string.data())
+ this->setp(__base, __base + _M_string.capacity());
+ else
+ this->setp(__base, __end);
this->pbump(__o);
// egptr() always tracks the string end. When !__testin,
// for the correct functioning of the streambuf inlines
diff -urN libstdc++-v3-orig/testsuite/27_io/basic_stringbuf/setbuf/char/4.cc libstdc++-v3/testsuite/27_io/basic_stringbuf/setbuf/char/4.cc
--- libstdc++-v3-orig/testsuite/27_io/basic_stringbuf/setbuf/char/4.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/27_io/basic_stringbuf/setbuf/char/4.cc 2004-10-05 21:08:36.000000000 +0200
@@ -0,0 +1,58 @@
+// 2004-10-06 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2004 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ using namespace std;
+ bool test __attribute__((unused)) = true;
+
+ const unsigned max_size = 1 << 18;
+
+ char ref[max_size];
+ memset(ref, '\0', max_size);
+
+ char src[max_size * 2];
+ memset(src, '\1', max_size * 2);
+
+ for (unsigned i = 128; i <= max_size; i *= 2)
+ {
+ char* dest = new char[i * 2];
+ memset(dest, '\0', i * 2);
+
+ stringbuf sbuf;
+ sbuf.pubsetbuf(dest, i);
+
+ sbuf.sputn(src, i * 2);
+ VERIFY( !memcmp(dest + i, ref, i) );
+
+ delete[] dest;
+ }
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/27_io/basic_stringbuf/setbuf/wchar_t/4.cc libstdc++-v3/testsuite/27_io/basic_stringbuf/setbuf/wchar_t/4.cc
--- libstdc++-v3-orig/testsuite/27_io/basic_stringbuf/setbuf/wchar_t/4.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/27_io/basic_stringbuf/setbuf/wchar_t/4.cc 2004-10-05 21:07:43.000000000 +0200
@@ -0,0 +1,58 @@
+// 2004-10-06 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2004 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ using namespace std;
+ bool test __attribute__((unused)) = true;
+
+ const unsigned max_size = 1 << 18;
+
+ wchar_t ref[max_size];
+ wmemset(ref, L'\0', max_size);
+
+ wchar_t src[max_size * 2];
+ wmemset(src, L'\1', max_size * 2);
+
+ for (unsigned i = 128; i <= max_size; i *= 2)
+ {
+ wchar_t* dest = new wchar_t[i * 2];
+ wmemset(dest, L'\0', i * 2);
+
+ wstringbuf sbuf;
+ sbuf.pubsetbuf(dest, i);
+
+ sbuf.sputn(src, i * 2);
+ VERIFY( !wmemcmp(dest + i, ref, i) );
+
+ delete[] dest;
+ }
+}
+
+int main()
+{
+ test01();
+ return 0;
+}