public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix -Wstringop-overflow warning in 23_containers/vector/types/1.cc
@ 2024-05-27 20:07 François Dumont
  2024-05-27 20:18 ` Sam James
  2024-05-28 10:28 ` Jonathan Wakely
  0 siblings, 2 replies; 10+ messages in thread
From: François Dumont @ 2024-05-27 20:07 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

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

In C++98 this test fails with:

Excess errors:
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h:452: 
warning: 'void* __builtin_memcpy(void*, const void*, long unsigned int)' 
writing between 2 and 9223372036854775806 bytes into a region of size 0 
overflows the destination [-Wstringop-overflow=]

The attached patch avoids this warning.

     libstdc++: Fix -Wstringop-overflow warning coming from std::vector

     Make vector<>::_M_range_insert implementation more transparent to 
the compiler checks.

     Extend local copies of members to the whole method scope so that 
all branches benefit
     from those.

     libstdc++-v3/ChangeLog:

             * include/bits/vector.tcc
             (std::vector<>::_M_range_insert(iterator, _FwdIt, _FwdIt, 
forward_iterator_tag)):
             Use local copies of members to call the different algorithms.

Ok to commit if all tests passes ?

François

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

diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index 36b27dce7b9..671929dee55 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -885,83 +885,80 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
 	if (__first != __last)
 	  {
+	    // Make local copies of these members because the compiler
+	    // thinks the allocator can alter them if 'this' is globally
+	    // reachable.
+	    pointer __start = this->_M_impl._M_start;
+	    pointer __end = this->_M_impl._M_end_of_storage;
+	    pointer __finish = this->_M_impl._M_finish;
+	    pointer __pos = __position.base();
+	    _Tp_alloc_type& __allocator = _M_get_Tp_allocator();
+
+	    if (__pos < __start || __finish < __pos)
+	      __builtin_unreachable();
+
 	    const size_type __n = std::distance(__first, __last);
-	    if (size_type(this->_M_impl._M_end_of_storage
-			  - this->_M_impl._M_finish) >= __n)
+	    if (size_type(__end - __finish) >= __n)
 	      {
-		const size_type __elems_after = end() - __position;
-		pointer __old_finish(this->_M_impl._M_finish);
+		const size_type __elems_after = __end - __pos;
+		pointer __old_finish(__finish);
 		if (__elems_after > __n)
 		  {
 		    _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
-		    std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
-						this->_M_impl._M_finish,
-						this->_M_impl._M_finish,
-						_M_get_Tp_allocator());
-		    this->_M_impl._M_finish += __n;
+		    __finish = std::__uninitialized_move_a
+		      (__finish - __n, __finish, __finish, __allocator);
 		    _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
-		    _GLIBCXX_MOVE_BACKWARD3(__position.base(),
-					    __old_finish - __n, __old_finish);
-		    std::copy(__first, __last, __position);
+		    _GLIBCXX_MOVE_BACKWARD3
+		      (__pos, __old_finish - __n, __old_finish);
+		    std::copy(__first, __last, __pos);
 		  }
 		else
 		  {
 		    _ForwardIterator __mid = __first;
 		    std::advance(__mid, __elems_after);
 		    _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
-		    std::__uninitialized_copy_a(__mid, __last,
-						this->_M_impl._M_finish,
-						_M_get_Tp_allocator());
-		    this->_M_impl._M_finish += __n - __elems_after;
+		    __finish = std::__uninitialized_copy_a
+		      (__mid, __last, __finish, __allocator);
 		    _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after);
-		    std::__uninitialized_move_a(__position.base(),
-						__old_finish,
-						this->_M_impl._M_finish,
-						_M_get_Tp_allocator());
-		    this->_M_impl._M_finish += __elems_after;
+		    __finish = std::__uninitialized_move_a
+		      (__pos, __old_finish, __finish, __allocator);
 		    _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after);
-		    std::copy(__first, __mid, __position);
+		    std::copy(__first, __mid, __pos);
 		  }
+
+		this->_M_impl._M_finish = __finish;
 	      }
 	    else
 	      {
-		// Make local copies of these members because the compiler
-		// thinks the allocator can alter them if 'this' is globally
-		// reachable.
-		pointer __old_start = this->_M_impl._M_start;
-		pointer __old_finish = this->_M_impl._M_finish;
-
+		const size_type __size = size_type(__finish - __start);
 		const size_type __len =
 		  _M_check_len(__n, "vector::_M_range_insert");
+		if (__len < __n + __size)
+		  __builtin_unreachable();
+
 		pointer __new_start(this->_M_allocate(__len));
 		pointer __new_finish(__new_start);
 		__try
 		  {
 		    __new_finish
 		      = std::__uninitialized_move_if_noexcept_a
-		      (__old_start, __position.base(),
-		       __new_start, _M_get_Tp_allocator());
+		      (__start, __pos, __new_start, __allocator);
 		    __new_finish
-		      = std::__uninitialized_copy_a(__first, __last,
-						    __new_finish,
-						    _M_get_Tp_allocator());
+		      = std::__uninitialized_copy_a
+		      (__first, __last, __new_finish, __allocator);
 		    __new_finish
 		      = std::__uninitialized_move_if_noexcept_a
-		      (__position.base(), __old_finish,
-		       __new_finish, _M_get_Tp_allocator());
+		      (__pos, __finish, __new_finish, __allocator);
 		  }
 		__catch(...)
 		  {
-		    std::_Destroy(__new_start, __new_finish,
-				  _M_get_Tp_allocator());
+		    std::_Destroy(__new_start, __new_finish, __allocator);
 		    _M_deallocate(__new_start, __len);
 		    __throw_exception_again;
 		  }
-		std::_Destroy(__old_start, __old_finish,
-			      _M_get_Tp_allocator());
+		std::_Destroy(__start, __finish, __allocator);
 		_GLIBCXX_ASAN_ANNOTATE_REINIT;
-		_M_deallocate(__old_start,
-			      this->_M_impl._M_end_of_storage - __old_start);
+		_M_deallocate(__start, __end - __start);
 		this->_M_impl._M_start = __new_start;
 		this->_M_impl._M_finish = __new_finish;
 		this->_M_impl._M_end_of_storage = __new_start + __len;

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2024-06-03 19:08 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-27 20:07 [PATCH] Fix -Wstringop-overflow warning in 23_containers/vector/types/1.cc François Dumont
2024-05-27 20:18 ` Sam James
2024-05-27 20:58   ` François Dumont
2024-05-28 10:28 ` Jonathan Wakely
2024-05-30  5:11   ` François Dumont
2024-05-30 11:07     ` Jonathan Wakely
2024-06-03  4:56       ` [PATCH] Fix -Wstringop-overflow warning in 23_containers/vector/types/1.cc PR109849 François Dumont
2024-06-03 16:20         ` Jonathan Wakely
2024-06-03 17:46           ` François Dumont
2024-06-03 19:08             ` 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).