[gcc r11-10129] libstdc++: Check for invalid syntax_option_type values in <regex>

Jonathan Wakely redi@gcc.gnu.org
Thu Jul 7 23:33:10 GMT 2022


https://gcc.gnu.org/g:ece2bb2adc2c801c4be3c6d0e2656aee633aaddd

commit r11-10129-gece2bb2adc2c801c4be3c6d0e2656aee633aaddd
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Sep 29 13:48:15 2021 +0100

    libstdc++: Check for invalid syntax_option_type values in <regex>
    
    The standard says that it is invalid for more than one grammar element
    to be set in a value of type regex_constants::syntax_option_type. This
    adds a check in the regex compiler andthrows an exception if an invalid
    value is used.
    
    Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/regex_compiler.h (_Compiler::_S_validate): New
            function.
            * include/bits/regex_compiler.tcc (_Compiler::_Compiler): Use
            _S_validate to check flags.
            * include/bits/regex_error.h (_S_grammar): New error code for
            internal use.
            * testsuite/28_regex/basic_regex/ctors/grammar.cc: New test.
    
    (cherry picked from commit 9ca4c42a3b756e54a92ff8e1ac6c396b680b7839)

Diff:
---
 libstdc++-v3/include/bits/regex_compiler.h         | 20 ++++++++
 libstdc++-v3/include/bits/regex_compiler.tcc       | 10 +---
 libstdc++-v3/include/bits/regex_error.h            |  3 +-
 .../28_regex/basic_regex/ctors/grammar.cc          | 53 ++++++++++++++++++++++
 4 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
index de4d9d01a48..f224fcb06e0 100644
--- a/libstdc++-v3/include/bits/regex_compiler.h
+++ b/libstdc++-v3/include/bits/regex_compiler.h
@@ -144,6 +144,26 @@ namespace __detail
 	return ret;
       }
 
+      static _FlagT
+      _S_validate(_FlagT __f)
+      {
+	using namespace regex_constants;
+	switch (__f & (ECMAScript|basic|extended|awk|grep|egrep))
+	  {
+	  case ECMAScript:
+	  case basic:
+	  case extended:
+	  case awk:
+	  case grep:
+	  case egrep:
+	    return __f;
+	  case _FlagT(0):
+	    return __f | ECMAScript;
+	  default:
+	    std::__throw_regex_error(_S_grammar, "conflicting grammar options");
+	  }
+      }
+
       _FlagT              _M_flags;
       _ScannerT           _M_scanner;
       shared_ptr<_RegexT> _M_nfa;
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index 9550d06aea7..ea07bc2428e 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -65,15 +65,7 @@ namespace __detail
     _Compiler<_TraitsT>::
     _Compiler(_IterT __b, _IterT __e,
 	      const typename _TraitsT::locale_type& __loc, _FlagT __flags)
-    : _M_flags((__flags
-		& (regex_constants::ECMAScript
-		   | regex_constants::basic
-		   | regex_constants::extended
-		   | regex_constants::grep
-		   | regex_constants::egrep
-		   | regex_constants::awk))
-	       ? __flags
-	       : __flags | regex_constants::ECMAScript),
+    : _M_flags(_S_validate(__flags)),
       _M_scanner(__b, __e, _M_flags, __loc),
       _M_nfa(make_shared<_RegexT>(__loc, _M_flags)),
       _M_traits(_M_nfa->_M_traits),
diff --git a/libstdc++-v3/include/bits/regex_error.h b/libstdc++-v3/include/bits/regex_error.h
index 9212fd31552..af07325c307 100644
--- a/libstdc++-v3/include/bits/regex_error.h
+++ b/libstdc++-v3/include/bits/regex_error.h
@@ -61,7 +61,8 @@ namespace regex_constants
       _S_error_badrepeat,
       _S_error_complexity,
       _S_error_stack,
-      _S_null
+      _S_null,
+      _S_grammar
     };
 
   /** The expression contained an invalid collating element name. */
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/grammar.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/grammar.cc
new file mode 100644
index 00000000000..fd8531c4530
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/grammar.cc
@@ -0,0 +1,53 @@
+// { dg-do run { target c++11 } }
+#include <regex>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::regex re{""};
+  VERIFY( re.flags() & std::regex::ECMAScript );
+
+  std::regex re2{"", std::regex::flag_type{}};
+  VERIFY( re2.flags() == std::regex::flag_type() ); // See also PR 83598
+}
+
+void
+test02()
+{
+  // A valid value of type syntax_option_type shall have at most one of the
+  // grammar elements ECMAScript, basic, extended, awk, grep, egrep, set.
+
+  try
+  {
+    std::regex{"", std::regex::ECMAScript|std::regex::basic};
+    VERIFY( false );
+  }
+  catch (const std::regex_error&)
+  {
+  }
+
+  try
+  {
+    std::regex{"", std::regex::extended|std::regex::basic};
+    VERIFY( false );
+  }
+  catch (const std::regex_error&)
+  {
+  }
+
+  try
+  {
+    std::regex{"", std::regex::grep|std::regex::basic};
+    VERIFY( false );
+  }
+  catch (const std::regex_error&)
+  {
+  }
+}
+
+int main()
+{
+  test01();
+  test02();
+}


More information about the Libstdc++-cvs mailing list