diff mbox

std::regex: Implement LWG DR 2329 and DR 2332

Message ID 20141210013745.GJ3134@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Dec. 10, 2014, 1:37 a.m. UTC
Two defect reports that protect against dangerous uses of std::regex
involving dangling references to temporaries:
http://cplusplus.github.io/LWG/lwg-defects.html#2329
http://cplusplus.github.io/LWG/lwg-defects.html#2332

Tested x86_64-linux & powerpc64-linux, committed to trunk.
diff mbox

Patch

commit 616ac2600bcb71c505fa6286084a166500a8bf66
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Dec 10 01:20:42 2014 +0000

    Implement LWG DR 2329 and DR 2332.
    
    	* include/bits/regex.h (regex_match, regex_search): LWG DR 2329,
    	add deleted overloads for rvalue strings.
    	(regex_iterator, regex_token_iterator): LWG DR 2332, add deleted
    	constructors for rvalue regexes.
    	* testsuite/28_regex/algorithms/regex_match/dr2329_neg.cc: New.
    	* testsuite/28_regex/algorithms/regex_search/dr2329_neg.cc: New.
    	* testsuite/28_regex/iterators/regex_iterator/ctors/char/dr2332_neg.cc:
    	New.
    	* testsuite/28_regex/iterators/regex_token_iterator/ctors/char/
    	dr2332_neg.cc: New.

diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index 6ff9a82..cb6bc93 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -2063,6 +2063,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		= regex_constants::match_default)
     { return regex_match(__s.begin(), __s.end(), __m, __re, __flags); }
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2329. regex_match() with match_results should forbid temporary strings
+  /// Prevent unsafe attempts to get match_results from a temporary string.
+  template<typename _Ch_traits, typename _Ch_alloc,
+	   typename _Alloc, typename _Ch_type, typename _Rx_traits>
+    bool
+    regex_match(const basic_string<_Ch_type, _Ch_traits, _Ch_alloc>&&,
+		match_results<typename basic_string<_Ch_type,
+		_Ch_traits, _Ch_alloc>::const_iterator, _Alloc>&,
+		const basic_regex<_Ch_type, _Rx_traits>&,
+		regex_constants::match_flag_type
+		= regex_constants::match_default) = delete;
+
   /**
    * @brief Indicates if there is a match between the regular expression @p e
    * and a C-style null-terminated string.
@@ -2239,6 +2252,20 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		 = regex_constants::match_default)
     { return regex_search(__s.begin(), __s.end(), __m, __e, __f); }
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2329. regex_search() with match_results should forbid temporary strings
+  /// Prevent unsafe attempts to get match_results from a temporary string.
+  template<typename _Ch_traits, typename _Ch_alloc,
+	   typename _Alloc, typename _Ch_type,
+	   typename _Rx_traits>
+    bool
+    regex_search(const basic_string<_Ch_type, _Ch_traits, _Ch_alloc>&&,
+		 match_results<typename basic_string<_Ch_type,
+		 _Ch_traits, _Ch_alloc>::const_iterator, _Alloc>&,
+		 const basic_regex<_Ch_type, _Rx_traits>&,
+		 regex_constants::match_flag_type
+		 = regex_constants::match_default) = delete;
+
   // std [28.11.4] Function template regex_replace
   /**
    * @brief Search for a regular expression within a range for multiple times,
@@ -2437,6 +2464,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  *this = regex_iterator();
       }
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2332. regex_iterator should forbid temporary regexes
+      regex_iterator(_Bi_iter, _Bi_iter, const regex_type&&,
+		     regex_constants::match_flag_type
+		     = regex_constants::match_default) = delete;
       /**
        * Copy constructs a %regex_iterator.
        */
@@ -2618,6 +2650,25 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_subs(__submatches, *(&__submatches+1)), _M_n(0)
       { _M_init(__a, __b); }
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2332. regex_token_iterator should forbid temporary regexes
+      regex_token_iterator(_Bi_iter, _Bi_iter, const regex_type&&, int = 0,
+			   regex_constants::match_flag_type =
+			   regex_constants::match_default) = delete;
+      regex_token_iterator(_Bi_iter, _Bi_iter, const regex_type&&,
+			   const std::vector<int>&,
+			   regex_constants::match_flag_type =
+			   regex_constants::match_default) = delete;
+      regex_token_iterator(_Bi_iter, _Bi_iter, const regex_type&&,
+			   initializer_list<int>,
+			   regex_constants::match_flag_type =
+			   regex_constants::match_default) = delete;
+      template <std::size_t N>
+	regex_token_iterator(_Bi_iter, _Bi_iter, const regex_type&&,
+			     const int (&)[N],
+			     regex_constants::match_flag_type =
+			     regex_constants::match_default) = delete;
+
       /**
        * @brief Copy constructs a %regex_token_iterator.
        * @param __rhs [IN] A %regex_token_iterator to copy.
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/dr2329_neg.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/dr2329_neg.cc
new file mode 100644
index 0000000..3070f93
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/dr2329_neg.cc
@@ -0,0 +1,28 @@ 
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <regex>
+
+void
+test01()
+{
+  std::smatch m;
+  regex_match(std::string{}, m, std::regex{"."}); // { dg-error "deleted" }
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/dr2332_neg.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/dr2332_neg.cc
new file mode 100644
index 0000000..2381ddb
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/dr2332_neg.cc
@@ -0,0 +1,28 @@ 
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <regex>
+
+void
+test01()
+{
+  std::smatch m;
+  regex_search(std::string{}, m, std::regex{"."}); // { dg-error "deleted" }
+}
diff --git a/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/ctors/char/dr2332_neg.cc b/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/ctors/char/dr2332_neg.cc
new file mode 100644
index 0000000..2a72b4f
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/ctors/char/dr2332_neg.cc
@@ -0,0 +1,29 @@ 
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <regex>
+
+void
+test01()
+{
+  using iter_type = std::regex_iterator<const char*>;
+  const char* s = "";
+  iter_type(s, s, std::regex{}); // { dg-error "deleted" }
+}
diff --git a/libstdc++-v3/testsuite/28_regex/iterators/regex_token_iterator/ctors/char/dr2332_neg.cc b/libstdc++-v3/testsuite/28_regex/iterators/regex_token_iterator/ctors/char/dr2332_neg.cc
new file mode 100644
index 0000000..6ff5870
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/iterators/regex_token_iterator/ctors/char/dr2332_neg.cc
@@ -0,0 +1,39 @@ 
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <regex>
+
+void
+test01()
+{
+  using iter_type = std::regex_token_iterator<const char*>;
+  const char* s = "";
+
+  iter_type(s, s, std::regex{});	// { dg-error "deleted" }
+
+  std::vector<int> v;
+  iter_type(s, s, std::regex{}, v);	// { dg-error "deleted" }
+
+  std::initializer_list<int> il = {1};
+  iter_type(s, s, std::regex{}, il);	// { dg-error "deleted" }
+
+  const int i[2] = { };
+  iter_type(s, s, std::regex{}, i);	// { dg-error "deleted" }
+}