From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 2990E3858022; Tue, 4 Jul 2023 12:45:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2990E3858022 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1688474718; bh=Te+X+BQcVRG2taQ6DOlA4gIUZBxB6wu84ZWu/x71IEc=; h=From:To:Subject:Date:From; b=Tw/V6hje0C/7aFtHthQTgOTAbPXE67CbYbT+j5WUXKE5kbrUbUgeUAtvy60vdJTDl 5mG+YMMg8Det55oOWlIZ/KwBiBFG2e74WDXgjLsV37B/jur3BBxQyZlPtxAz6fIfpu jMcGR8QVyrK9PkJl9QrIS0M41ZUy3UPhD2Y1xi9M= From: "hal.finkel.oss at gmail dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/110542] New: use of allocated storage after deallocation in a constant expression: std::array of std::vector Date: Tue, 04 Jul 2023 12:45:17 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: libstdc++ X-Bugzilla-Version: 13.1.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: hal.finkel.oss at gmail dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D110542 Bug ID: 110542 Summary: use of allocated storage after deallocation in a constant expression: std::array of std::vector Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: hal.finkel.oss at gmail dot com Target Milestone: --- For this test case: ``` #include #include struct s_t { std::vector, 1>> v; constexpr void rz(std::size_t n) { v.resize(n); for (auto &x : v) for (auto &w : x) w.resize(n); } }; constexpr std::size_t test1() { s_t s; s.rz(1); s.rz(2); return 1; } int main() { static_assert(test1() =3D=3D 1); } ``` g++ -std=3Dc++20 13.1.0 (and GCC trunk as of today on https://gcc.godbolt.o= rg/): ERROR: ``` tc1.cpp: In function =E2=80=98int main()=E2=80=99: tc1.cpp:21:25: error: non-constant condition for static assertion 21 | static_assert(test1() =3D=3D 1); | ~~~~~~~~^~~~ tc1.cpp:21:22: in =E2=80=98constexpr=E2=80=99 expansion of =E2=80=98test1= ()=E2=80=99 tc1.cpp:16:7: in =E2=80=98constexpr=E2=80=99 expansion of =E2=80=98s.s_t:= :rz(2)=E2=80=99 tc1.cpp:9:49: in =E2=80=98constexpr=E2=80=99 expansion of =E2=80=98(& w)->std::vector::resize(n)=E2=80=99 /gcc-13.1.0/include/c++/13/bits/stl_vector.h:1011:21: in =E2=80=98constex= pr=E2=80=99 expansion of =E2=80=98((std::vector*)this)->std::vector::_M_default_append((__= new_size - ((std::vector*)this)->std::vector::size()))=E2=80=99 /gcc-13.1.0/include/c++/13/bits/vector.tcc:676:16: in =E2=80=98constexpr= =E2=80=99 expansion of =E2=80=98std::vector::_S_relocate(__old_start, __old_finish, __new_= start, (* &((std::vector*)this)->std::vector::.std::_Vector_base= >::_M_get_Tp_allocator()))=E2=80=99 /gcc-13.1.0/include/c++/13/bits/stl_vector.h:504:26: in =E2=80=98constexp= r=E2=80=99 expansion of =E2=80=98std::__relocate_a >(__first, __last,= __result, (* & __alloc))=E2=80=99 /gcc-13.1.0/include/c++/13/bits/stl_uninitialized.h:1142:33: in =E2=80=98= constexpr=E2=80=99 expansion of =E2=80=98std::__relocate_a_1(std::__niter_base= (__first), std::__niter_base(__last), std::__niter_base(__result), (* & __alloc))=E2=80=99 /gcc-13.1.0/include/c++/13/bits/stl_uninitialized.h:1122:35: in =E2=80=98= constexpr=E2=80=99 expansion of =E2=80=98std::__relocate_a_1, allocator >(__first, __last, __out, (* & __alloc))=E2=80=99 /gcc-13.1.0/include/c++/13/bits/stl_uninitialized.h:1100:26: in =E2=80=98= constexpr=E2=80=99 expansion of =E2=80=98std::__relocate_object_a >(std::__addressof((* & __cur.__gnu_cxx::__normal_iterator::operator*())), std::__addressof((* __first)), (* & __alloc))=E2= =80=99 /gcc-13.1.0/include/c++/13/bits/stl_uninitialized.h:1072:26: in =E2=80=98= constexpr=E2=80=99 expansion of =E2=80=98std::allocator_traits >::construc= t((* & __alloc), __dest, (* & std::move((*(int*)__orig))))=E2=80=99 /gcc-13.1.0/include/c++/13/bits/alloc_traits.h:539:21: in =E2=80=98conste= xpr=E2=80=99 expansion of =E2=80=98std::construct_at(__p, (* & std::forward((* & __args#0))))=E2=80=99 tc1.cpp:21:25: error: use of allocated storage after deallocation in a cons= tant expression In file included from /gcc-13.1.0/include/c++/13/vector:63, from tc1.cpp:1: /gcc-13.1.0/include/c++/13/bits/allocator.h:195:52: note: allocated here 195 | return static_cast<_Tp*>(::operator new(__n)); | ~~~~~~~~~~~~~~^~~~~ ``` clang -std=3Dc++20 15, (and 16 and trunk as of today on https://gcc.godbolt= .org/, noting that these appear to use headers from libstdc++ gcc-12.2.0; below is from clang 15 using GCC 13.1.0 headers): ERROR: ``` tc1.cpp:21:17: error: static assertion expression is not an integral consta= nt expression static_assert(test1() =3D=3D 1); ^~~~~~~~~~~~ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_algobase.h:931:11: note: assignment to object outside its lifetime is not allowed in a constant expression *__first =3D __tmp; ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_algobase.h:977:7: note: in call to '__fill_a1(&{*new int[2]#4}[1], &{*new int[2]#4}[2], {*new int[2]#4}[0])' { std::__fill_a1(__first, __last, __value); } ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_algobase.h:1128:7: note: in call to '__fill_a(&{*new int[2]#4}[1], &{*new int[2]#4}[2], {*new int[2]#4}[0])' std::__fill_a(__first, __first + __n, __value); ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_algobase.h:1157:14: note: in call to '__fill_n_a(&{*new int[2]#4}[1], 1, {*new int[2]#4}[0], {{{{}}}})' return std::__fill_n_a(__first, std::__size_to_integer(__n), __value, ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_uninitialized.h:668:18: note: in call to 'fill_n(&{*new int[2]#4}[1], 1, {*new int[2]#4}[0])' __first =3D std::fill_n(__first, __n - 1, *__val); ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_uninitialized.h:704:14: note: in call to '__uninit_default_n(&{*new int[2]#4}[1], 2)' return __uninitialized_default_n_1<__is_trivial(_ValueType) ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_uninitialized.h:773:14: note: (skipping 1 call in backtrace; use -fconstexpr-backtrace-limit=3D0 to= see all) { return std::__uninitialized_default_n(__first, __n); } ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= vector.tcc:668:9: note: in call to '__uninitialized_default_n_a(&{*new int[2]#4}[0], 2, {*new std::array, 1>[2]#2}[1]._M_elems[0]._Vector_base::_M_impl)' std::__uninitialized_default_n_a(__new_start + __size, ^ /gcc-13.1.0/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/bits/= stl_vector.h:1011:4: note: in call to '&{*new std::array, 1>[2]#2}[1]._M_elems[0]->_M_default_append(2)' _M_default_append(__new_size - size()); ^ tc1.cpp:9:43: note: in call to '&{*new std::array, 1>[2]#2}[1]._M_elems[0]->resize(2)' for (auto &x : v) for (auto &w : x) w.resize(n); ^ tc1.cpp:16:5: note: in call to '&s->rz(2)' s.rz(2); ^ tc1.cpp:21:17: note: in call to 'test1()' static_assert(test1() =3D=3D 1); ^ 1 error generated. ``` clang -std=3Dc++20 -stdlib=3Dlibc++ 15, 16, and trunk as of today on https://gcc.godbolt.org/): OK I realize that this might be two compiler bugs, and I see, e.g., GCC bug 101777, but the fact that both GCC and clang provide what seem like they mi= ght be the same semantic error, a use after deallocation, albeit pointing at slightly different places in the libstdc++ headers, both on the second resi= ze, and it works with libc++, is why I suspect that it might be an issue in the library (and the error message here is different from the one in 101777). O= r, of course, my code has UB and the compilers are correct.=