[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-22 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

--- Comment #6 from GCC Commits  ---
The master branch has been updated by Jonathan Wakely :

https://gcc.gnu.org/g:04f2be72b1deecd6c6d454e000cfc0cb16db957c

commit r16-819-g04f2be72b1deecd6c6d454e000cfc0cb16db957c
Author: Jonathan Wakely 
Date:   Wed May 21 15:29:02 2025 +0100

libstdc++: Fix vector(from_range_t, R&&) for exceptions [PR120367]

Because this constructor delegates to vector(a) the object has been
fully constructed and the destructor will run if an exception happens.
That means we need to set _M_finish == _M_start so that the destructor
doesn't try to destroy any elements.

libstdc++-v3/ChangeLog:

PR libstdc++/120367
* include/bits/stl_vector.h (_M_range_initialize): Initialize
_M_impl._M_finish.
* testsuite/23_containers/vector/cons/from_range.cc: Check with
a type that throws on construction.
exceptions during construction.

Reviewed-by: Patrick Palka 

[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-21 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

--- Comment #5 from Jonathan Wakely  ---
Reduced:

#include 

int main()
{
  struct X
  {
X(int) { throw 1; } // Cannot successfully construct an X.
~X() { VERIFY(false); } // So should never need to destroy one.
  };

  try
  {
int i[1]{};
std::vector v(std::from_range, i);
  }
  catch (int)
  {
  }
}

[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-21 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

--- Comment #4 from Jonathan Wakely  ---
Here's the fix:

--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1969,7 +1969,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_range_initialize_n(_Iterator __first, _Sentinel __last,
  size_type __n)
{
- pointer __start = this->_M_impl._M_start =
+ pointer __start = this->_M_impl._M_start = this->_M_impl._M_finish =
this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
  this->_M_impl._M_end_of_storage = __start + __n;
  this->_M_impl._M_finish


Because vector(from_range_t, R&&) uses constructor delegation, it means that
the ~vector destructor will be run if an exception happens during the
delegating constructor.

When ~vector runs it destroys all the objects in the range [_M_start,_M_finish)
but we never set _M_finish, so it just destroys garbage.

The fix is to set _M_finish == _M_start so that ~vector has nothing to do.

[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-21 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

Jonathan Wakely  changed:

   What|Removed |Added

 Status|NEW |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |redi at gcc dot gnu.org

--- Comment #3 from Jonathan Wakely  ---
Mine then (I think we're deallocating an invalid pointer).

[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-20 Thread rguenth at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

Richard Biener  changed:

   What|Removed |Added

   Last reconfirmed||2025-05-21
 Ever confirmed|0   |1
   Priority|P3  |P2
 Status|UNCONFIRMED |NEW

[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-20 Thread ppalka at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

Patrick Palka  changed:

   What|Removed |Added

 CC||ppalka at gcc dot gnu.org

--- Comment #2 from Patrick Palka  ---
GCC 14 preprocessed sources compile/run fine with GCC 15/trunk, suggesting a
library change is the cause.  Maybe the vector(from_range_t) constructor
additions?

[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-20 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

--- Comment #1 from Andrew Pinski  ---
#0  __pthread_kill_implementation (threadid=,
signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x7788b9b3 in __pthread_kill_internal (signo=6, threadid=) at pthread_kill.c:78
#2  0x7783e646 in __GI_raise (sig=sig@entry=6) at
../sysdeps/posix/raise.c:26
#3  0x778287f3 in __GI_abort () at abort.c:79
#4  0x77829130 in __libc_message (fmt=,
fmt@entry=0x779bb6a8 "%s\n") at ../sysdeps/posix/libc_fatal.c:150
#5  0x778959f7 in malloc_printerr (str=str@entry=0x779be290 "double
free or corruption (out)") at malloc.c:5515
#6  0x778976e0 in _int_free (av=0x779fac80 ,
p=0x407db0, have_lock=) at malloc.c:4455
#7  0x77899d35 in __GI___libc_free (mem=) at
malloc.c:3258
#8  0x00404695 in std::__new_allocator::deallocate
(this=0x41b420, __p=0x407dc0 
"\300;\347\367\377\177", __n=140737350674973) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/new_allocator.h:172
#9  0x00403f38 in std::allocator::deallocate (this=0x41b420,
__p=0x407dc0 
"\300;\347\367\377\177", __n=140737350674973) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/allocator.h:215
#10 std::allocator_traits >::deallocate (__a=...,
__p=0x407dc0 
"\300;\347\367\377\177", __n=140737350674973) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/alloc_traits.h:649
#11 std::__cxx11::basic_string,
std::allocator >::_M_destroy (this=0x41b420, __size=140737350674972) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/basic_string.h:305
#12 0x00403b8a in std::__cxx11::basic_string, std::allocator >::_M_dispose (this=0x41b420) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/basic_string.h:299
#13 0x0040374c in std::__cxx11::basic_string, std::allocator >::~basic_string (this=0x41b420)
at /home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/basic_string.h:896
#14 0x0040461d in std::destroy_at, std::allocator > > (__location=0x41b420) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/stl_construct.h:88
#15 0x0040439b in std::_Destroy, std::allocator > > (__pointer=0x41b420) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/stl_construct.h:164
#16 0x0040415c in std::_Destroy, std::allocator >*> (__first=0x41b420, __last=0x0)
at /home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/stl_construct.h:212
#17 0x00403a4a in std::_Destroy, std::allocator >*,
std::__cxx11::basic_string, std::allocator >
> (__first=0x41b360, __last=0x0) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/alloc_traits.h:1045
#18 std::vector,
std::allocator >, std::allocator, std::allocator > > >::~vector
(this=0x7fffda70) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/stl_vector.h:790
#19 0x004027df in std::vector, std::allocator >,
std::allocator,
std::allocator > >
>::vector
> >, main():: > >(std::from_range_t,
std::ranges::transform_view, std::allocator >,
std::allocator,
std::allocator > > > >, main():: > &&, const
std::allocator,
std::allocator > > &) (this=0x7fffda70, __rg=..., __a=...) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/stl_vector.h:778
#20 0x004026dc in
std::ranges::to >,
std::ranges::transform_view
> >, main():: >
>(std::ranges::transform_view, std::allocator >,
std::allocator,
std::allocator > > > >, main():: > &&) (__r=...) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/ranges:9432
#21 0x00402477 in std::ranges::to
> >, main():: >
>(std::ranges::transform_view, std::allocator >,
std::allocator,
std::allocator > > > >, main():: > &&) (__r=...) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/ranges:9534
#22 0x004024ad in
std::ranges::__detail::_To2::operator()
> >, main():: >
>(std::ranges::transform_view, std::allocator >,
std::allocator,
std::allocator > > > >, main():: > &&) const
(this=0x7fffd8e7, __r=...) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/ranges:9602
#23 0x004024e6 in operator()<>(void) const (__closure=0x7fffda08)
at /home/apinski/upstream-gcc-isel/include/c++/16.0.0/ranges:1070
#24 0x0040269d in
std::__invoke_impl >,
std::ranges::views::__adaptor::_Partial
>::operator()
>,
std::ranges::transform_view
> >, main():: > >(this
std::ranges::views::__adaptor::_Partial
>&&,
std::ranges::transform_view
> >, main():: >&&)::&>(std::__invoke_other, struct {...} &) (__f=...) at
/home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/invoke.h:63
#25 0x0040266c in
std::__invoke
>::operator()
>,
std::ranges::transform_view
> >, main():: > >(this
std::ranges::views::__adaptor::_Partial
>&&,
std::ranges::transform_view
> >, main():: >&&)::&>(struct
{...} &) (__fn=...)
at /home/apinski/upstream-gcc-isel/include/c++/16.0.0/bits/invoke.h:99
#26 0x0040251b in
std::__apply_impl
>::operator()
>,
std::ranges::transform_view
> >, main():: > >(th

[Bug libstdc++/120367] [15/16 Regression] C++23 ranges::transform | ranges::to exception catching (segfault)

2025-05-20 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367

Andrew Pinski  changed:

   What|Removed |Added

   Target Milestone|--- |15.2
   Keywords||EH, needs-bisection,
   ||wrong-code