This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Do not take address of empty string front


On 20/06/15 12:59 +0100, Jonathan Wakely wrote:
On 20/06/15 12:03 +0200, François Dumont wrote:
Hi

  2 experimental tests are failing in debug mode because
__do_str_codecvt is sometimes taking address of string front() and
back() even if empty. It wasn't use so not a big issue but it still
seems better to avoid. I propose to rather use string begin() to get
buffer address.

But derefencing begin() is still undefined for an empty string.
Shouldn't that fail for debug mode too? Why change one form of
undefined behaviour that we diagnose to another form that we don't
diagnose?

It would be better if that function didn't do any work when the input
range is empty:

--- a/libstdc++-v3/include/bits/locale_conv.h
+++ b/libstdc++-v3/include/bits/locale_conv.h
@@ -58,6 +58,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                   _OutStr& __outstr, const _Codecvt& __cvt, _State& __state,
                   size_t& __count, _Fn __fn)
   {
+      if (__first == __last)
+       {
+         __outstr.clear();
+         return true;
+       }
+
     size_t __outchars = 0;
     auto __next = __first;
     const auto __maxlen = __cvt.max_length() + 1;

This makes that change, and also moves wstring_convert into the
ABI-tagged __cxx11 namespace, and fixes a copy&paste error in the
exception thrown from wbuffer_convert.

Tested powerpc64le-linux, committed to trunk.

François, your changes to add extra checks in std::string are still
useful separately.

commit 4ab3f0a76f7e18074c91c4644cbfdf23084e93ba
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jun 22 13:47:24 2015 +0100

    	* include/bits/locale_conv.h (__do_str_codecvt): Handle empty range.
    	(wstring_convert): Move into __cxx11 namespace.
    	(wbuffer_convert(streambuf*, _Codecvt*, state_type)): Fix exception
    	message.

diff --git a/libstdc++-v3/include/bits/locale_conv.h b/libstdc++-v3/include/bits/locale_conv.h
index 61b535c..fd99499 100644
--- a/libstdc++-v3/include/bits/locale_conv.h
+++ b/libstdc++-v3/include/bits/locale_conv.h
@@ -58,6 +58,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		     _OutStr& __outstr, const _Codecvt& __cvt, _State& __state,
 		     size_t& __count, _Fn __fn)
     {
+      if (__first == __last)
+	{
+	  __outstr.clear();
+	  return true;
+	}
+
       size_t __outchars = 0;
       auto __next = __first;
       const auto __maxlen = __cvt.max_length() + 1;
@@ -150,6 +156,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __str_codecvt_out(__first, __last, __outstr, __cvt, __state, __n);
     }
 
+_GLIBCXX_BEGIN_NAMESPACE_CXX11
+
   /// String conversions
   template<typename _Codecvt, typename _Elem = wchar_t,
 	   typename _Wide_alloc = allocator<_Elem>,
@@ -301,6 +309,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       bool			_M_with_strings = false;
     };
 
+_GLIBCXX_END_NAMESPACE_CXX11
+
   /// Buffer conversions
   template<typename _Codecvt, typename _Elem = wchar_t,
 	   typename _Tr = char_traits<_Elem>>
@@ -325,7 +335,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_buf(__bytebuf), _M_cvt(__pcvt), _M_state(__state)
       {
 	if (!_M_cvt)
-	  __throw_logic_error("wstring_convert");
+	  __throw_logic_error("wbuffer_convert");
 
 	_M_always_noconv = _M_cvt->always_noconv();
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]