From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id B588A3858C41; Fri, 19 May 2023 12:49:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B588A3858C41 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1684500584; bh=ZiaOmYfjV126dLPQdfjpCIW65MQSYVJyJtxn3p8+82k=; h=From:To:Subject:Date:In-Reply-To:References:From; b=QRZO3vIGnkKYlqIYrLRHt61L7W2zUe0A35Bt5GID56RjLc+tDvAT+tSE3PdHUVuz3 IQB42sWpDr9d7gK0nGpRwL6BCIE2u6j3NcWh4+Ei/qLOJkMsrjqIa0qvjdxDX7dTJG FpL0nqKmCUKQxm4QGbQQMGr2ojDu3UeIAj098kGU= From: "redi at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/109889] [13/14 Regression] Segfault in __run_exit_handlers since r13-5309-gc3c6c307792026 Date: Fri, 19 May 2023 12:49:43 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: libstdc++ X-Bugzilla-Version: 14.0 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: redi at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: 13.2 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: 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=3D109889 --- Comment #11 from Jonathan Wakely --- The test looks like this: #include #include int main() {=20 typedef int value_type; typedef __gnu_cxx::throw_allocator_random allocator_type; try { __gnu_test::check_deallocate_null(); } catch (std::logic_error&) { // Should throw logic_error to catch null erase. } return 0; } Where check_deallocate_null does: template bool check_deallocate_null() { // Let's not core here... Alloc a; a.deallocate(0, 1); a.deallocate(0, 10); return true; } The first call to deallocate results in a call to: // See if a particular address and allocation size has been saved. inline map_alloc_type::iterator check_allocated(void* p, size_t size) { map_alloc_type::iterator found =3D map_alloc().find(p); if (found =3D=3D map_alloc().end()) { std::string error("annotate_base::check_allocated by value " "null erase!\n"); log_to_string(error, make_entry(p, size)); std::__throw_logic_error(error.c_str()); } This creates a debug mode iterator (found) and attaches it to the list of iterators for the static map created here: static map_alloc_type& map_alloc() { static map_alloc_type _S_map; return _S_map; } The call to map_alloc().end() then creates a second iterator, which is atta= ched to the list, and then detached when it goes out of scope. Then we throw an exception, which is caught in main() and we return from main(). The first iterator, found, was not destroyed, and so was not detached from = the list of active iterators. When the map gets destroyed it detaches the itera= tor and calls its _M_reset() member to note that the iterator is now invalid (because the map it refers to no logner exists). But that iterator only exi= sted on the stack of check_allocated, and calling _M_reset() on that stack addre= ss corrupts the stack. The found iterator should have been destroyed when the exception was thrown= and the stack was unwound.=