public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Fix null pointer dereferences in __gnu_cxx::rope
@ 2020-12-02 12:30 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2020-12-02 12:30 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1593 bytes --]

This fixes UBsan errors like:

/usr/include/c++/10/ext/ropeimpl.h:593:9: runtime error: member access within null pointer of type 'struct _RopeRep'
/usr/include/c++/10/ext/ropeimpl.h:593:9: runtime error: member call on null pointer of type 'struct _Rope_rep_base'
/usr/include/c++/10/ext/rope:556:17: runtime error: reference binding to null pointer of type 'struct allocator_type'
/usr/include/c++/10/ext/ropeimpl.h:593:9: runtime error: reference binding to null pointer of type 'struct allocator_type'
/usr/include/c++/10/ext/rope:1700:30: runtime error: member call on null pointer of type 'struct new_allocator'
/usr/include/c++/10/ext/new_allocator.h:105:29: runtime error: member call on null pointer of type 'struct new_allocator'
/usr/include/c++/10/ext/rope:1702:26: runtime error: reference binding to null pointer of type 'const struct allocator'
/usr/include/c++/10/bits/allocator.h:148:34: runtime error: reference binding to null pointer of type 'const struct new_allocator'
/usr/include/c++/10/ext/rope:1664:39: runtime error: reference binding to null pointer of type 'const struct allocator'
/usr/include/c++/10/ext/rope:1665:9: runtime error: reference binding to null pointer of type 'const struct allocator_type'
/usr/include/c++/10/ext/rope:725:36: runtime error: reference binding to null pointer of type 'const struct allocator_type'
/usr/include/c++/10/ext/rope:614:64: runtime error: reference binding to null pointer of type 'const struct allocator_type'

The problem is calling r->_M_get_allocator() when r is null.

Tested powerpc64le-linux. Committed to trunk.


[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 9380 bytes --]

commit 74270a546cf75aad5e2db642b4715728d4da7904
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Dec 2 12:29:00 2020

    libstdc++: Fix null pointer dereferences in __gnu_cxx::rope
    
    This fixes UBsan errors like:
    
    /usr/include/c++/10/ext/ropeimpl.h:593:9: runtime error: member access within null pointer of type 'struct _RopeRep'
    /usr/include/c++/10/ext/ropeimpl.h:593:9: runtime error: member call on null pointer of type 'struct _Rope_rep_base'
    /usr/include/c++/10/ext/rope:556:17: runtime error: reference binding to null pointer of type 'struct allocator_type'
    /usr/include/c++/10/ext/ropeimpl.h:593:9: runtime error: reference binding to null pointer of type 'struct allocator_type'
    /usr/include/c++/10/ext/rope:1700:30: runtime error: member call on null pointer of type 'struct new_allocator'
    /usr/include/c++/10/ext/new_allocator.h:105:29: runtime error: member call on null pointer of type 'struct new_allocator'
    /usr/include/c++/10/ext/rope:1702:26: runtime error: reference binding to null pointer of type 'const struct allocator'
    /usr/include/c++/10/bits/allocator.h:148:34: runtime error: reference binding to null pointer of type 'const struct new_allocator'
    /usr/include/c++/10/ext/rope:1664:39: runtime error: reference binding to null pointer of type 'const struct allocator'
    /usr/include/c++/10/ext/rope:1665:9: runtime error: reference binding to null pointer of type 'const struct allocator_type'
    /usr/include/c++/10/ext/rope:725:36: runtime error: reference binding to null pointer of type 'const struct allocator_type'
    /usr/include/c++/10/ext/rope:614:64: runtime error: reference binding to null pointer of type 'const struct allocator_type'
    
    The problem is calling r->_M_get_allocator() when r is null.
    
    libstdc++-v3/ChangeLog:
    
            * include/ext/rope (rope::_S_concat_char_iter)
            (rope::_S_destr_concat_char_iter): Add allocator parameter.
            (rope::push_back, rope::append, rope::insert, operator+):
            Pass allocator.
            * include/ext/ropeimpl.h (rope::_S_concat_char_iter)
            (rope::_S_destr_concat_char_iter): Add allocator parameter
            and use it.
            (_Rope_char_ref_proxy::operator=(_CharT)): Pass allocator.

diff --git a/libstdc++-v3/include/ext/rope b/libstdc++-v3/include/ext/rope
index 8479acd8f74..de6ecdd524f 100644
--- a/libstdc++-v3/include/ext/rope
+++ b/libstdc++-v3/include/ext/rope
@@ -1612,19 +1612,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       static _RopeRep* _S_concat_char_iter(_RopeRep* __r,
 					   const _CharT* __iter,
-					   size_type __slen);
-      // Concatenate rope and char ptr, copying __s.
+					   size_type __slen,
+					   allocator_type& __a);
+      // Concatenate rope and char ptr, copying __iter.
       // Should really take an arbitrary iterator.
       // Result is counted in refcount.
       static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r,
 						 const _CharT* __iter,
-						 size_type __slen)
+						 size_type __slen,
+						 allocator_type& __a)
 	// As above, but one reference to __r is about to be
 	// destroyed.  Thus the pieces may be recycled if all
 	// relevant reference counts are 1.
 #ifdef __GC
 	// We can't really do anything since refcounts are unavailable.
-      { return _S_concat_char_iter(__r, __iter, __slen); }
+      { return _S_concat_char_iter(__r, __iter, __slen, __a); }
 #else
       ;
 #endif
@@ -1913,9 +1915,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       void
       push_back(_CharT __x)
       {
+	allocator_type __a = _M_get_allocator();
 	_RopeRep* __old = this->_M_tree_ptr;
 	this->_M_tree_ptr
-	  = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1);
+	  = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1, __a);
 	_S_unref(__old);
       }
 
@@ -2115,8 +2118,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       rope&
       append(const _CharT* __iter, size_type __n)
       {
+	allocator_type __a = _M_get_allocator();
 	_RopeRep* __result =
-	  _S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n);
+	  _S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n, __a);
 	_S_unref(this->_M_tree_ptr);
 	this->_M_tree_ptr = __result;
 	return *this;
@@ -2133,8 +2137,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       rope&
       append(const _CharT* __s, const _CharT* __e)
       {
+	allocator_type __a = _M_get_allocator();
 	_RopeRep* __result =
-	  _S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s);
+	  _S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s, __a);
 	_S_unref(this->_M_tree_ptr);
 	this->_M_tree_ptr = __result;
 	return *this;
@@ -2156,8 +2161,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       rope&
       append(_CharT __c)
       {
+	allocator_type __a = _M_get_allocator();
 	_RopeRep* __result =
-	  _S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1);
+	  _S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1, __a);
 	_S_unref(this->_M_tree_ptr);
 	this->_M_tree_ptr = __result;
 	return *this;
@@ -2239,7 +2245,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	_Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p));
 	_Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr,
 						__p, size()));
-	_Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n));
+	_Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n,
+							     _M_get_allocator()));
 	// _S_ destr_concat_char_iter should be safe here.
 	// But as it stands it's probably not a win, since __left
 	// is likely to have additional references.
@@ -2843,8 +2850,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef rope<_CharT, _Alloc> rope_type;
       std::size_t __rlen = rope_type::_S_char_ptr_len(__right);
+      _Alloc __a = __left.get_allocator();
       return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
-						      __right, __rlen));
+						      __right, __rlen, __a));
     }
 
   template <class _CharT, class _Alloc>
@@ -2861,8 +2869,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator+(const rope<_CharT, _Alloc>& __left, _CharT __right)
     {
       typedef rope<_CharT, _Alloc> rope_type;
+      _Alloc __a = __left.get_allocator();
       return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
-						      &__right, 1));
+						      &__right, 1, __a));
     }
 
   template <class _CharT, class _Alloc>
diff --git a/libstdc++-v3/include/ext/ropeimpl.h b/libstdc++-v3/include/ext/ropeimpl.h
index c5d3a0c1aef..e571847d2c5 100644
--- a/libstdc++-v3/include/ext/ropeimpl.h
+++ b/libstdc++-v3/include/ext/ropeimpl.h
@@ -524,7 +524,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template <class _CharT, class _Alloc>
     typename rope<_CharT, _Alloc>::_RopeRep*
     rope<_CharT, _Alloc>::
-    _S_concat_char_iter(_RopeRep* __r, const _CharT*__s, std::size_t __slen)
+    _S_concat_char_iter(_RopeRep* __r, const _CharT*__s, std::size_t __slen,
+			allocator_type& __a)
     {
       using std::size_t;
       _RopeRep* __result;
@@ -534,8 +535,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  return __r;
 	}
       if (0 == __r)
-	return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
-						__r->_M_get_allocator());
+	return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
       if (__r->_M_tag == __detail::_S_leaf
 	  && __r->_M_size + __slen <= size_t(_S_copy_max))
 	{
@@ -564,8 +564,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      return __result;
 	    }
 	}
-      _RopeRep* __nright =
-	__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator());
+      _RopeRep* __nright = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
       __try
 	{
 	  __r->_M_ref_nonnil();
@@ -585,17 +584,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     typename rope<_CharT,_Alloc>::_RopeRep*
     rope<_CharT,_Alloc>::
     _S_destr_concat_char_iter(_RopeRep* __r, const _CharT* __s,
-			      std::size_t __slen)
+			      std::size_t __slen, allocator_type& __a)
     {
       using std::size_t;
       _RopeRep* __result;
       if (0 == __r)
-	return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
-						__r->_M_get_allocator());
+	return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
       size_t __count = __r->_M_ref_count;
       size_t __orig_size = __r->_M_size;
       if (__count > 1)
-	return _S_concat_char_iter(__r, __s, __slen);
+	return _S_concat_char_iter(__r, __s, __slen, __a);
       if (0 == __slen)
 	{
 	  __r->_M_ref_count = 2;      // One more than before
@@ -632,8 +630,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      return __r;
 	    }
 	}
-      _RopeRep* __right =
-	__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator());
+      _RopeRep* __right = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
       __r->_M_ref_nonnil();
       __try
 	{ __result = _S_tree_concat(__r, __right); }
@@ -1500,9 +1497,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _Self_destruct_ptr __left(_My_rope::_S_substring(__old, 0, _M_pos));
       _Self_destruct_ptr __right(_My_rope::_S_substring(__old, _M_pos + 1,
 							__old->_M_size));
+      typename _RopeRep::allocator_type __a = _M_root->_M_get_allocator();
       _Self_destruct_ptr __result_left(_My_rope::
 				       _S_destr_concat_char_iter(__left,
-								 &__c, 1));
+								 &__c, 1,
+								 __a));
 
       _RopeRep* __result = _My_rope::_S_concat(__result_left, __right);
 #ifndef __GC

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-12-02 12:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-02 12:30 [committed] libstdc++: Fix null pointer dereferences in __gnu_cxx::rope Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).