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

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