[v3] correctly handle NUL characters in stringbufs, plus cosmetic tweaks
Phil Edwards
pedwards@disaster.jaj.com
Fri Jul 13 13:50:00 GMT 2001
This patch fixes a critical bug in stringbufs, as well as some other
completely uninteresting changes. Lots of analysis on the libstdc++ list
about the NUL bug; basically, if a stringstream tries to read data out of
a string which has embedded NULs, then we incorrectly stop at the first one.
Tested on x86/linux, applied to trunk and branch.
2001-07-13 Phil Edwards <pme@sources.redhat.com>
* include/bits/std_sstream.h (basic_stringbuf::basic_stringbuf(string):
Initialize _M_string with pointer-and-size constructor, not just
pointer. Fix some comments.
* testsuite/21_strings/ctor_copy_dtor.cc (test03): New test.
* testsuite/27_io/stringbuf.cc (test02): Remove unused variable.
(test03): Add embedded-NUL tests.
* mkcheck.in: When printing totals, match the order of the tests.
* include/bits/stringfwd.h: Use same declaration keywords.
* include/bits/std_iosfwd.h: Cosmetic spacing.
Index: mkcheck.in
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/mkcheck.in,v
retrieving revision 1.59
diff -u -3 -p -r1.59 mkcheck.in
--- mkcheck.in 2001/05/22 18:48:19 1.59
+++ mkcheck.in 2001/07/13 20:42:55
@@ -436,7 +436,7 @@ TEST_TIME_END=$($TIMER_COMMAND)
# grep can count faster than we can...
total_failures=`expr ${shared_fail} + ${static_fail}`
total_successes=`expr ${shared_pass} + ${static_pass}`
-resultstext="pass/fail results: ${shared_pass}/${shared_fail} shared + ${static_pass}/${static_fail} static = ${total_successes}/${total_failures} total"
+resultstext="pass/fail results: ${static_pass}/${static_fail} static + ${shared_pass}/${shared_fail} shared = ${total_successes}/${total_failures} total"
if [ $total_failures -eq 0 ]; then
resultstext="${resultstext}, WIN WIN"
fi
Index: include/bits/std_iosfwd.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/std_iosfwd.h,v
retrieving revision 1.7
diff -u -3 -p -r1.7 std_iosfwd.h
--- std_iosfwd.h 2001/06/26 21:22:57 1.7
+++ std_iosfwd.h 2001/07/13 20:42:55
@@ -100,7 +100,7 @@ namespace std
typedef basic_ios<char> ios;
typedef basic_streambuf<char> streambuf;
typedef basic_istream<char> istream;
- typedef basic_ostream<char> ostream;
+ typedef basic_ostream<char> ostream;
typedef basic_iostream<char> iostream;
typedef basic_stringbuf<char> stringbuf;
typedef basic_istringstream<char> istringstream;
Index: include/bits/std_sstream.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/std_sstream.h,v
retrieving revision 1.7
diff -u -3 -p -r1.7 std_sstream.h
--- std_sstream.h 2001/06/12 22:14:08 1.7
+++ std_sstream.h 2001/07/13 20:42:55
@@ -75,7 +75,7 @@ namespace std
explicit
basic_stringbuf(const __string_type& __str,
ios_base::openmode __mode = ios_base::in | ios_base::out)
- : __streambuf_type(), _M_string(__str.c_str())
+ : __streambuf_type(), _M_string(__str.data(), __str.size())
{ _M_stringbuf_init(__mode); }
// Get and set:
@@ -84,7 +84,7 @@ namespace std
{
if (_M_mode & ios_base::out)
{
- // This is the deal: _M_string.size() is value that
+ // This is the deal: _M_string.size() is a value that
// represents the size of the intial string that makes
// _M_string, and may not be the correct size of the
// current stringbuf internal buffer.
@@ -116,7 +116,7 @@ namespace std
// re-allocation of the internal string object, _M_string.
_M_buf_size = _M_string.size();
- // NB: Start ostringstream buffers at 1024 bytes. This is an
+ // NB: Start ostringstream buffers at 512 bytes. This is an
// experimental value (pronounced "arbitrary" in some of the
// hipper english-speaking countries), and can be changed to
// suite particular needs.
Index: include/bits/stringfwd.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/stringfwd.h,v
retrieving revision 1.3
diff -u -3 -p -r1.3 stringfwd.h
--- stringfwd.h 2001/03/07 22:22:41 1.3
+++ stringfwd.h 2001/07/13 20:42:55
@@ -43,9 +43,9 @@ namespace std
template<class _CharT>
struct char_traits;
- template<> class char_traits<char>;
+ template<> struct char_traits<char>;
#ifdef _GLIBCPP_USE_WCHAR_T
- template<> class char_traits<wchar_t>;
+ template<> struct char_traits<wchar_t>;
#endif
template<typename _Alloc>
Index: testsuite/21_strings/ctor_copy_dtor.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/21_strings/ctor_copy_dtor.cc,v
retrieving revision 1.6
diff -u -3 -p -r1.6 ctor_copy_dtor.cc
--- ctor_copy_dtor.cc 2001/05/12 16:51:41 1.6
+++ ctor_copy_dtor.cc 2001/07/13 20:42:55
@@ -1,6 +1,6 @@
// 1999-06-04 bkoz
-// Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+// Copyright (C) 1999, 2000, 2001 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
@@ -176,9 +176,28 @@ void test02()
#endif
}
+void test03()
+{
+ bool test = true;
+ const char* with_nulls = "This contains \0 a zero byte.";
+
+ // These are tests to see how basic_string handles data with NUL
+ // bytes. Obviously basic_string(char*) will halt at the first one, but
+ // nothing else should.
+ std::string s1 (with_nulls, 28);
+ VERIFY( s1.size() == 28 );
+ std::string s2 (s1);
+ VERIFY( s2.size() == 28 );
+
+#ifdef DEBUG_ASSERT
+ assert(test);
+#endif
+}
+
int main()
{
test01();
test02();
+ test03();
return 0;
}
Index: testsuite/27_io/stringbuf.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/stringbuf.cc,v
retrieving revision 1.4
diff -u -3 -p -r1.4 stringbuf.cc
--- stringbuf.cc 2001/05/12 16:51:42 1.4
+++ stringbuf.cc 2001/07/13 20:42:55
@@ -1,6 +1,6 @@
// 981208 bkoz test functionality of basic_stringbuf for char_type == char
-// Copyright (C) 1997-1999, 2000 Free Software Foundation, Inc.
+// Copyright (C) 1997-2001 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
@@ -54,7 +54,6 @@ bool test02() {
// test member functions
bool test03() {
bool test = true;
- std::string str_tmp;
//stringbuf::str()
VERIFY( strb_01.str() == str_01 );
@@ -71,6 +70,18 @@ bool test03() {
VERIFY( d1 != d2 ); //these should be the same
VERIFY( str_01.length() == d1 );
VERIFY( strb_01.str() == strb_03.str() ); //ditto
+
+ // stringbuf::str(string&) and stringbuf::stringbuf(string&), where the
+ // string in question contains embedded NUL characters. Note that in this
+ // embedded-NUL situation, the size must be passed to the string ctor.
+ std::string str_nulls ("eschew \0 obfuscation", 20); // tested in 21_strings
+ std::stringbuf strb_normal (str_01);
+ std::stringbuf strb_nulls (str_nulls);
+ strb_normal.str(str_nulls); // tried using 'strb_01' rather than declaring
+ // another variable, but then test04 broke!
+ VERIFY( strb_nulls.in_avail() == str_nulls.size() );
+ VERIFY( strb_nulls.str().size() == 20 );
+ VERIFY( strb_normal.in_avail() == str_nulls.size() );
#ifdef DEBUG_ASSERT
assert(test);
More information about the Libstdc++
mailing list