From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 0B1E1385116D for ; Fri, 28 Oct 2022 14:27:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0B1E1385116D Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1666967276; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=FFU5qXdkl8csQX889baSK8K2EcJKZn53LBL3dMts2OQ=; b=HJfdJcdCq6SB/0mtFWEuqBw7P2m0t/gDaHPLfBpVeQi3ueK7L3znS+834L3nvwSupUAhsA BRV8miKcspChrlh2DmypRKjwu7XFTmnoBs4v0j0aKv115iHjcj9xOfNb4WlU+egbN957/m 3irtm9nTk7bAow2k2hhUe+gkujj3xcY= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-505-kaGKt_mPP7a3DXB_Z6MW6g-1; Fri, 28 Oct 2022 10:27:55 -0400 X-MC-Unique: kaGKt_mPP7a3DXB_Z6MW6g-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4F72C3C0ED47; Fri, 28 Oct 2022 14:27:55 +0000 (UTC) Received: from localhost (unknown [10.33.37.13]) by smtp.corp.redhat.com (Postfix) with ESMTP id 147C440C835A; Fri, 28 Oct 2022 14:27:54 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix allocator propagation in regex algorithms [PR107376] Date: Fri, 28 Oct 2022 15:27:54 +0100 Message-Id: <20221028142754.145622-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP,URI_HEX autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Tested powerpc64le-linux. Pushed to trunk. -- >8 -- The PR points out that we assume the match_results allocator is default constuctible, which might not be true. We also have a related issue with unwanted propagation from an object that might have an unequal allocator. Ideally we use the same allocator type for _State_info::_M_match_queue but that would be an ABI change now. We should investigate if that can be done without breaking anything, which might be possible because the _Executor object is short-lived and never leaks out of the regex_match, regex_search, and regex_replace algorithms. If we change the mangled name for _Executor then there would be no ODR violations when mixing old and new definitions. This commit does not attempt that. libstdc++-v3/ChangeLog: PR libstdc++/107376 * include/bits/regex_executor.h (_Executor::_Executor): Use same allocator for _M_cur_results and _M_results. * include/bits/regex_executor.tcc (_Executor::_M_main_dispatch): Prevent possibly incorrect allocator propagating to _M_cur_results. * testsuite/28_regex/algorithms/regex_match/107376.cc: New test. --- libstdc++-v3/include/bits/regex_executor.h | 17 +++-- libstdc++-v3/include/bits/regex_executor.tcc | 3 +- .../28_regex/algorithms/regex_match/107376.cc | 76 +++++++++++++++++++ 3 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h index dc0878ce678..cdafcd5523d 100644 --- a/libstdc++-v3/include/bits/regex_executor.h +++ b/libstdc++-v3/include/bits/regex_executor.h @@ -71,14 +71,15 @@ namespace __detail _ResultsVec& __results, const _RegexT& __re, _FlagT __flags) - : _M_begin(__begin), - _M_end(__end), - _M_re(__re), - _M_nfa(*__re._M_automaton), - _M_results(__results), - _M_rep_count(_M_nfa.size()), - _M_states(_M_nfa._M_start(), _M_nfa.size()), - _M_flags(__flags) + : _M_cur_results(__results.get_allocator()), + _M_begin(__begin), + _M_end(__end), + _M_re(__re), + _M_nfa(*__re._M_automaton), + _M_results(__results), + _M_rep_count(_M_nfa.size()), + _M_states(_M_nfa._M_start(), _M_nfa.size()), + _M_flags(__flags) { using namespace regex_constants; if (__flags & match_prev_avail) // ignore not_bol and not_bow diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc index b93e958075e..a5885ed34ba 100644 --- a/libstdc++-v3/include/bits/regex_executor.tcc +++ b/libstdc++-v3/include/bits/regex_executor.tcc @@ -124,9 +124,10 @@ namespace __detail break; std::fill_n(_M_states._M_visited_states, _M_nfa.size(), false); auto __old_queue = std::move(_M_states._M_match_queue); + auto __alloc = _M_cur_results.get_allocator(); for (auto& __task : __old_queue) { - _M_cur_results = std::move(__task.second); + _M_cur_results = _ResultsVec(std::move(__task.second), __alloc); _M_dfs(__match_mode, __task.first); } if (__match_mode == _Match_mode::_Prefix) diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc new file mode 100644 index 00000000000..da4f7ad0a23 --- /dev/null +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc @@ -0,0 +1,76 @@ +// { dg-do run { target c++11 } } +#include +#include +#include + +template +struct Alloc +{ + using value_type = T; + explicit Alloc(int) { } + template Alloc(const Alloc&) { } + + T* allocate(std::size_t n) + { return std::allocator().allocate(n); } + void deallocate(T* ptr, std::size_t n) + { std::allocator().deallocate(ptr, n); } + + bool operator==(const Alloc&) const { return true; } + bool operator!=(const Alloc&) const { return false; } +}; + +void +test_non_default_constructible() +{ + using sub_match = std::sub_match; + using alloc_type = Alloc; + using match_results = std::match_results; + match_results res(alloc_type(1)); + + std::regex_match("x", res, std::regex(".")); // PR libstdc++/107376 +} + +template +struct PropAlloc +{ + int id; + + using value_type = T; + explicit PropAlloc(int id) : id(id) { } + template PropAlloc(const PropAlloc& a) : id(a.id) { } + + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_copy_assignment = std::true_type; + + PropAlloc select_on_container_copy_construction() const + { return PropAlloc(0); } + + T* allocate(std::size_t n) + { return std::allocator().allocate(n); } + void deallocate(T* ptr, std::size_t n) + { std::allocator().deallocate(ptr, n); } + + bool operator==(const PropAlloc& a) const { return id == a.id; } + bool operator!=(const PropAlloc& a) const { return id != a.id; } +}; + +void +test_propagation() +{ + using sub_match = std::sub_match; + using alloc_type = PropAlloc; + using match_results = std::match_results; + alloc_type alloc(107376); + match_results res(alloc); + + std::regex re("..", std::regex_constants::__polynomial); + std::regex_match("xx", res, re); + + VERIFY( res.get_allocator() == alloc ); +} + +int main() +{ + test_non_default_constructible(); + test_propagation(); +} -- 2.37.3