$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r84371 - in trunk: boost/regex/v4 libs/regex/test/regress
From: john_at_[hidden]
Date: 2013-05-19 07:12:15
Author: johnmaddock
Date: 2013-05-19 07:12:14 EDT (Sun, 19 May 2013)
New Revision: 84371
URL: http://svn.boost.org/trac/boost/changeset/84371
Log:
When a {} repeat sequence is invalid or incomplete, and the language is Perl, then backtrack and treat the sequence as a literal, not a repeat operator.
Fixes #8569.
Text files modified: 
   trunk/boost/regex/v4/basic_regex_parser.hpp           |    68 ++++++++++++++++++++++++++++++--------- 
   trunk/libs/regex/test/regress/test_simple_repeats.cpp |    25 +++++++-------                          
   2 files changed, 64 insertions(+), 29 deletions(-)
Modified: trunk/boost/regex/v4/basic_regex_parser.hpp
==============================================================================
--- trunk/boost/regex/v4/basic_regex_parser.hpp	(original)
+++ trunk/boost/regex/v4/basic_regex_parser.hpp	2013-05-19 07:12:14 EDT (Sun, 19 May 2013)
@@ -1070,26 +1070,46 @@
    // skip whitespace:
    while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
       ++m_position;
-   // fail if at end:
    if(this->m_position == this->m_end)
    {
-      fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
-      return false;
+      if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
+      {
+         fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
+         return false;
+      }
+      // Treat the opening '{' as a literal character, rewind to start of error:
+      --m_position;
+      while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
+      return parse_literal();
    }
    // get min:
    v = this->m_traits.toi(m_position, m_end, 10);
    // skip whitespace:
-   while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
-      ++m_position;
    if(v < 0)
    {
-      fail(regex_constants::error_badbrace, this->m_position - this->m_base);
-      return false;
+      if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
+      {
+         fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
+         return false;
+      }
+      // Treat the opening '{' as a literal character, rewind to start of error:
+      --m_position;
+      while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
+      return parse_literal();
    }
-   else if(this->m_position == this->m_end)
+   while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
+      ++m_position;
+   if(this->m_position == this->m_end)
    {
-      fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
-      return false;
+      if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
+      {
+         fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
+         return false;
+      }
+      // Treat the opening '{' as a literal character, rewind to start of error:
+      --m_position;
+      while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
+      return parse_literal();
    }
    min = v;
    // see if we have a comma:
@@ -1102,8 +1122,15 @@
          ++m_position;
       if(this->m_position == this->m_end)
       {
-         fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
-         return false;
+         if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
+         {
+            fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
+            return false;
+         }
+         // Treat the opening '{' as a literal character, rewind to start of error:
+         --m_position;
+         while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
+         return parse_literal();
       }
       // get the value if any:
       v = this->m_traits.toi(m_position, m_end, 10);
@@ -1120,8 +1147,15 @@
    // OK now check trailing }:
    if(this->m_position == this->m_end)
    {
-      fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
-      return false;
+      if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
+      {
+         fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
+         return false;
+      }
+      // Treat the opening '{' as a literal character, rewind to start of error:
+      --m_position;
+      while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
+      return parse_literal();
    }
    if(isbasic)
    {
@@ -1144,8 +1178,10 @@
       ++m_position;
    else
    {
-      fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
-      return false;
+      // Treat the opening '{' as a literal character, rewind to start of error:
+      --m_position;
+      while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
+      return parse_literal();
    }
    //
    // finally go and add the repeat, unless error:
Modified: trunk/libs/regex/test/regress/test_simple_repeats.cpp
==============================================================================
--- trunk/libs/regex/test/regress/test_simple_repeats.cpp	(original)
+++ trunk/libs/regex/test/regress/test_simple_repeats.cpp	2013-05-19 07:12:14 EDT (Sun, 19 May 2013)
@@ -179,21 +179,20 @@
 {
    using namespace boost::regex_constants;
 
-   TEST_INVALID_REGEX("a{}", perl);
-   TEST_INVALID_REGEX("a{", perl);
-   TEST_INVALID_REGEX("a{1", perl);
-   TEST_INVALID_REGEX("a{1,", perl);
-   TEST_INVALID_REGEX("a{1,2", perl);
-   TEST_INVALID_REGEX("a{ 1 , 2 ", perl);
-   TEST_INVALID_REGEX("a{ }", perl);
-   TEST_INVALID_REGEX("a}", perl);
+   TEST_REGEX_SEARCH("a{}", basic, "a{}", match_default, make_array(0, 3, -2, -2));
+   TEST_REGEX_SEARCH("a{", basic, "a{", match_default, make_array(0, 2, -2, -2));
+   TEST_REGEX_SEARCH("a{1", basic, "a{1", match_default, make_array(0, 3, -2, -2));
+   TEST_REGEX_SEARCH("a{1,", basic, "a{1,", match_default, make_array(0, 4, -2, -2));
+   TEST_REGEX_SEARCH("a{1,2", basic, "a{1,2", match_default, make_array(0, 5, -2, -2));
+   TEST_REGEX_SEARCH("a{ 1 , 2", basic, "a{ 1 , 2", match_default, make_array(0, 8, -2, -2));
+   TEST_REGEX_SEARCH("a{ }", basic, "a{ }", match_default, make_array(0, 4, -2, -2));
+   TEST_REGEX_SEARCH("a}", basic, "a}", match_default, make_array(0, 2, -2, -2));
    TEST_INVALID_REGEX("{1}", perl);
-   TEST_INVALID_REGEX("a{b}", perl);
-   TEST_INVALID_REGEX("a{1b}", perl);
-   TEST_INVALID_REGEX("a{1,b}", perl);
-   TEST_INVALID_REGEX("a{1,2v}", perl);
+   TEST_REGEX_SEARCH("a{b}", basic, "a{b}", match_default, make_array(0, 4, -2, -2));
+   TEST_REGEX_SEARCH("a{1b", basic, "a{1b", match_default, make_array(0, 4, -2, -2));
+   TEST_REGEX_SEARCH("a{1,b}", basic, "a{1,b}", match_default, make_array(0, 6, -2, -2));
+   TEST_REGEX_SEARCH("a{1,2v}", basic, "a{1,2v}", match_default, make_array(0, 7, -2, -2));
    TEST_INVALID_REGEX("a{2,1}", perl);
-
    // now try operator \\{\\} for POSIX basic regexes
    TEST_REGEX_SEARCH("a\\{2\\}", basic, "a", match_default, make_array(-2, -2));
    TEST_REGEX_SEARCH("a\\{2\\}", basic|no_intervals, "a{2}", match_default, make_array(0, 4, -2, -2));