public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/94540] New: stack overflow populating std::vector<very large type>
@ 2020-04-09 13:03 redi at gcc dot gnu.org
  2020-04-09 14:58 ` [Bug libstdc++/94540] " redi at gcc dot gnu.org
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2020-04-09 13:03 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94540

            Bug ID: 94540
           Summary: stack overflow populating std::vector<very large type>
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

#include <vector>

struct yooj_type { char data[20*1024*1024]; };

int main() {
  std::vector<yooj_type> v(1);
}

This dies with SIGSEGV due to a stack overflow, because a yooj_type temporary
is created on the stack in <bits/stl_uninitialized.h>:

  template<>
    struct __uninitialized_default_1<true>
    {
      template<typename _ForwardIterator>
        static void
        __uninit_default(_ForwardIterator __first, _ForwardIterator __last)
        {
          typedef typename iterator_traits<_ForwardIterator>::value_type
            _ValueType;

          std::fill(__first, __last, _ValueType());
        }
    };

We should either avoid using std::fill for large objects (for some arbitrary
meaning of large) or we should construct the first object in place and then use
that as the fill argument:

--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -549,7 +549,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          typedef typename iterator_traits<_ForwardIterator>::value_type
            _ValueType;

-         std::fill(__first, __last, _ValueType());
+         if (__first == __last)
+           return;
+
+         const _ValueType& __val
+           = *std::_Construct(std::__addressof(*__first));
+         if (++__first != __last)
+           std::fill(__first, __last, __val);
        }
     };

@@ -585,7 +591,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          typedef typename iterator_traits<_ForwardIterator>::value_type
            _ValueType;

-         return std::fill_n(__first, __n, _ValueType());
+         if (__size_to_integer(__n) <= 0)
+           return __first;
+
+         const _ValueType& __val
+           = *std::_Construct(std::__addressof(*__first));
+         return std::fill_n(++__first, __size_to_integer(__n) - 1, __val);
        }
     };

I'm concerned this will confuse the optimisers, but haven't checked yet.

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

* [Bug libstdc++/94540] stack overflow populating std::vector<very large type>
  2020-04-09 13:03 [Bug libstdc++/94540] New: stack overflow populating std::vector<very large type> redi at gcc dot gnu.org
@ 2020-04-09 14:58 ` redi at gcc dot gnu.org
  2020-06-17 21:50 ` cvs-commit at gcc dot gnu.org
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2020-04-09 14:58 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94540

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2020-04-09
             Status|UNCONFIRMED                 |ASSIGNED
     Ever confirmed|0                           |1
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org

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

* [Bug libstdc++/94540] stack overflow populating std::vector<very large type>
  2020-04-09 13:03 [Bug libstdc++/94540] New: stack overflow populating std::vector<very large type> redi at gcc dot gnu.org
  2020-04-09 14:58 ` [Bug libstdc++/94540] " redi at gcc dot gnu.org
@ 2020-06-17 21:50 ` cvs-commit at gcc dot gnu.org
  2020-06-17 21:52 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-06-17 21:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94540

--- Comment #1 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:632183ddcc8f3aead8b4fc63c4ab59a42ef9ad00

commit r11-1464-g632183ddcc8f3aead8b4fc63c4ab59a42ef9ad00
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jun 17 22:49:06 2020 +0100

    libstdc++: Avoid stack overflow in std::vector (PR 94540)

    The std::__uninitialized_default_n algorithm used by std::vector creates
    an initial object as a local variable then copies that into the
    destination range. If the object is too large for the stack this
    crashes. We should create the first object directly into the
    destination and then copy it from there.

    This doesn't fix the bug for C++98, because in that case the initial
    value is created as a default argument of the vector constructor i.e. in
    the user's code, not inside libstdc++. We can't prevent that.

            PR libstdc++/94540
            * include/bits/stl_uninitialized.h
(__uninitialized_default_1<true>):
            Construct the first value at *__first instead of on the stack.
            (__uninitialized_default_n_1<true>): Likewise.
            Improve comments on several of the non-standard algorithms.
            *
testsuite/20_util/specialized_algorithms/uninitialized_default/94540.cc:
            New test.
            *
testsuite/20_util/specialized_algorithms/uninitialized_default_n/94540.cc:
            New test.
            *
testsuite/20_util/specialized_algorithms/uninitialized_value_construct/94540.cc:
            New test.
            *
testsuite/20_util/specialized_algorithms/uninitialized_value_construct_n/94540.cc:
            New test.
            * testsuite/23_containers/vector/cons/94540.cc: New test.

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

* [Bug libstdc++/94540] stack overflow populating std::vector<very large type>
  2020-04-09 13:03 [Bug libstdc++/94540] New: stack overflow populating std::vector<very large type> redi at gcc dot gnu.org
  2020-04-09 14:58 ` [Bug libstdc++/94540] " redi at gcc dot gnu.org
  2020-06-17 21:50 ` cvs-commit at gcc dot gnu.org
@ 2020-06-17 21:52 ` redi at gcc dot gnu.org
  2023-06-23 16:13 ` cvs-commit at gcc dot gnu.org
  2023-06-23 16:19 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2020-06-17 21:52 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94540

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |FIXED
             Status|ASSIGNED                    |RESOLVED
   Target Milestone|---                         |11.0

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Fixed in master.

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

* [Bug libstdc++/94540] stack overflow populating std::vector<very large type>
  2020-04-09 13:03 [Bug libstdc++/94540] New: stack overflow populating std::vector<very large type> redi at gcc dot gnu.org
                   ` (2 preceding siblings ...)
  2020-06-17 21:52 ` redi at gcc dot gnu.org
@ 2023-06-23 16:13 ` cvs-commit at gcc dot gnu.org
  2023-06-23 16:19 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2023-06-23 16:13 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94540

--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-10 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:

https://gcc.gnu.org/g:7dba69b5e9977408921c635681a0daa34b813e16

commit r10-11468-g7dba69b5e9977408921c635681a0daa34b813e16
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jun 17 22:49:06 2020 +0100

    libstdc++: Avoid stack overflow in std::vector (PR 94540)

    The std::__uninitialized_default_n algorithm used by std::vector creates
    an initial object as a local variable then copies that into the
    destination range. If the object is too large for the stack this
    crashes. We should create the first object directly into the
    destination and then copy it from there.

    This doesn't fix the bug for C++98, because in that case the initial
    value is created as a default argument of the vector constructor i.e. in
    the user's code, not inside libstdc++. We can't prevent that.

            PR libstdc++/94540
            * include/bits/stl_uninitialized.h
(__uninitialized_default_1<true>):
            Construct the first value at *__first instead of on the stack.
            (__uninitialized_default_n_1<true>): Likewise.
            Improve comments on several of the non-standard algorithms.
            *
testsuite/20_util/specialized_algorithms/uninitialized_default/94540.cc:
            New test.
            *
testsuite/20_util/specialized_algorithms/uninitialized_default_n/94540.cc:
            New test.
            *
testsuite/20_util/specialized_algorithms/uninitialized_value_construct/94540.cc:
            New test.
            *
testsuite/20_util/specialized_algorithms/uninitialized_value_construct_n/94540.cc:
            New test.
            * testsuite/23_containers/vector/cons/94540.cc: New test.

    (cherry picked from commit 632183ddcc8f3aead8b4fc63c4ab59a42ef9ad00)

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

* [Bug libstdc++/94540] stack overflow populating std::vector<very large type>
  2020-04-09 13:03 [Bug libstdc++/94540] New: stack overflow populating std::vector<very large type> redi at gcc dot gnu.org
                   ` (3 preceding siblings ...)
  2023-06-23 16:13 ` cvs-commit at gcc dot gnu.org
@ 2023-06-23 16:19 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2023-06-23 16:19 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94540

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|11.0                        |10.5

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Backported for 10.5 too.

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

end of thread, other threads:[~2023-06-23 16:19 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-09 13:03 [Bug libstdc++/94540] New: stack overflow populating std::vector<very large type> redi at gcc dot gnu.org
2020-04-09 14:58 ` [Bug libstdc++/94540] " redi at gcc dot gnu.org
2020-06-17 21:50 ` cvs-commit at gcc dot gnu.org
2020-06-17 21:52 ` redi at gcc dot gnu.org
2023-06-23 16:13 ` cvs-commit at gcc dot gnu.org
2023-06-23 16:19 ` redi at gcc dot gnu.org

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).