Commit 5bcb66df by Tim Shen Committed by Tim Shen

re PR testsuite/61061 (FAIL: g++.dg/inherit/covariant7.C)

	PR libstdc++/61061
	PR libstdc++/61582
	* include/bits/regex_automaton.h (_NFA<>::_M_insert_state): Add
	a NFA state limit. If it's exceeded, regex_constants::error_space
	will be throwed.
	* include/bits/regex_automaton.tcc (_StateSeq<>::_M_clone): Use
	map (which is sparse) instead of vector. This reduce n times clones'
	cost from O(n^2) to O(n).
	* include/std/regex: Add map dependency.
	* testsuite/28_regex/algorithms/regex_match/ecma/char/61601.cc: New
	testcase.

From-SVN: r212185
parent ad9ec7b3
2014-07-01 Tim Shen <timshen@google.com> 2014-07-01 Tim Shen <timshen@google.com>
PR libstdc++/61061
PR libstdc++/61582
* include/bits/regex_automaton.h (_NFA<>::_M_insert_state): Add
a NFA state limit. If it's exceeded, regex_constants::error_space
will be throwed.
* include/bits/regex_automaton.tcc (_StateSeq<>::_M_clone): Use
map (which is sparse) instead of vector. This reduce n times clones'
cost from O(n^2) to O(n).
* include/std/regex: Add map dependency.
* testsuite/28_regex/algorithms/regex_match/ecma/char/61601.cc: New
testcase.
2014-07-01 Tim Shen <timshen@google.com>
PR libstdc++/61424 PR libstdc++/61424
* include/bits/regex.tcc (__regex_algo_impl<>): Use DFS for ECMAScript, * include/bits/regex.tcc (__regex_algo_impl<>): Use DFS for ECMAScript,
not just regex containing back-references. not just regex containing back-references.
......
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
* Do not attempt to use it directly. @headername{regex} * Do not attempt to use it directly. @headername{regex}
*/ */
// This macro defines the maximal state number a NFA can have.
#ifndef _GLIBCXX_REGEX_STATE_LIMIT
#define _GLIBCXX_REGEX_STATE_LIMIT 100000
#endif
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
namespace __detail namespace __detail
...@@ -254,6 +259,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -254,6 +259,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert_state(_StateT __s) _M_insert_state(_StateT __s)
{ {
this->push_back(std::move(__s)); this->push_back(std::move(__s));
if (this->size() > _GLIBCXX_REGEX_STATE_LIMIT)
__throw_regex_error(regex_constants::error_space);
return this->size()-1; return this->size()-1;
} }
......
...@@ -189,7 +189,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -189,7 +189,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_StateSeq<_TraitsT> _StateSeq<_TraitsT>
_StateSeq<_TraitsT>::_M_clone() _StateSeq<_TraitsT>::_M_clone()
{ {
std::vector<_StateIdT> __m(_M_nfa.size(), -1); std::map<_StateIdT, _StateIdT> __m;
std::stack<_StateIdT> __stack; std::stack<_StateIdT> __stack;
__stack.push(_M_start); __stack.push(_M_start);
while (!__stack.empty()) while (!__stack.empty())
...@@ -203,21 +203,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -203,21 +203,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__dup._M_opcode == _S_opcode_alternative if (__dup._M_opcode == _S_opcode_alternative
|| __dup._M_opcode == _S_opcode_repeat || __dup._M_opcode == _S_opcode_repeat
|| __dup._M_opcode == _S_opcode_subexpr_lookahead) || __dup._M_opcode == _S_opcode_subexpr_lookahead)
if (__dup._M_alt != _S_invalid_state_id && __m[__dup._M_alt] == -1) if (__dup._M_alt != _S_invalid_state_id
&& __m.count(__dup._M_alt) == 0)
__stack.push(__dup._M_alt); __stack.push(__dup._M_alt);
if (__u == _M_end) if (__u == _M_end)
continue; continue;
if (__dup._M_next != _S_invalid_state_id && __m[__dup._M_next] == -1) if (__dup._M_next != _S_invalid_state_id
&& __m.count(__dup._M_next) == 0)
__stack.push(__dup._M_next); __stack.push(__dup._M_next);
} }
for (auto __v : __m) for (auto __it : __m)
{ {
if (__v == -1) auto __v = __it.second;
continue;
auto& __ref = _M_nfa[__v]; auto& __ref = _M_nfa[__v];
if (__ref._M_next != _S_invalid_state_id) if (__ref._M_next != _S_invalid_state_id)
{ {
_GLIBCXX_DEBUG_ASSERT(__m[__ref._M_next] != -1); _GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_next) > 0);
__ref._M_next = __m[__ref._M_next]; __ref._M_next = __m[__ref._M_next];
} }
if (__ref._M_opcode == _S_opcode_alternative if (__ref._M_opcode == _S_opcode_alternative
...@@ -225,7 +226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -225,7 +226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|| __ref._M_opcode == _S_opcode_subexpr_lookahead) || __ref._M_opcode == _S_opcode_subexpr_lookahead)
if (__ref._M_alt != _S_invalid_state_id) if (__ref._M_alt != _S_invalid_state_id)
{ {
_GLIBCXX_DEBUG_ASSERT(__m[__ref._M_alt] != -1); _GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_alt) > 0);
__ref._M_alt = __m[__ref._M_alt]; __ref._M_alt = __m[__ref._M_alt];
} }
} }
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <map>
#include <cstring> #include <cstring>
#include <bits/regex_constants.h> #include <bits/regex_constants.h>
......
// { dg-options "-std=gnu++11" }
// Copyright (C) 2013-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/>.
// 28.11.2 regex_match
#include <regex>
#include <testsuite_hooks.h>
#include <testsuite_regex.h>
using namespace __gnu_test;
using namespace std;
// libstdc++/61601
void
test01()
{
try
{
regex r("((.*)$1{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100}{100})");
}
catch (const regex_error& e)
{
VERIFY(e.code() == regex_constants::error_space);
}
}
int
main()
{
test01();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment