summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2020-11-23 14:40:59 -0800
committerBenoit Daloze <eregontp@gmail.com>2020-12-02 18:42:02 +0100
commit9e73177d5362c1986814f411961b712967dc5f97 (patch)
treef0ddbddc3e24423cd39128c3bdebf07d7e6608d1
parent7546be2ca0de45bcc2a72d9b4ae0cd44a1322031 (diff)
Do not reduce quantifiers if it affects which text will be matched
Quantifier reduction when using +?)* and +?)+ should not be done as it affects which text will be matched. This removes the need for the RQ_PQ_Q ReduceType, so remove the enum entry and related switch case. Test that these are the only two patterns affected by testing all quantifier reduction tuples for both the captured and uncaptured cases and making sure the matched text is the same for both. Fixes [Bug #17341]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3808
-rw-r--r--regparse.c9
-rw-r--r--test/ruby/test_regexp.rb14
2 files changed, 15 insertions, 8 deletions
diff --git a/regparse.c b/regparse.c
index 7639db3bbe..24ff5b9a18 100644
--- a/regparse.c
+++ b/regparse.c
@@ -2187,7 +2187,6 @@ enum ReduceType {
RQ_AQ, /* to '*?' */
RQ_QQ, /* to '??' */
RQ_P_QQ, /* to '+)??' */
- RQ_PQ_Q /* to '+?)?' */
};
static enum ReduceType const ReduceTypeTable[6][6] = {
@@ -2197,7 +2196,7 @@ static enum ReduceType const ReduceTypeTable[6][6] = {
{RQ_A, RQ_A, RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL}, /* '+' */
{RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL, RQ_AQ, RQ_AQ}, /* '??' */
{RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL}, /* '*?' */
- {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */
+ {RQ_ASIS, RQ_ASIS, RQ_ASIS, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */
};
extern void
@@ -2234,12 +2233,6 @@ onig_reduce_nested_quantifier(Node* pnode, Node* cnode)
c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 1;
return ;
break;
- case RQ_PQ_Q:
- p->target = cnode;
- p->lower = 0; p->upper = 1; p->greedy = 1;
- c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 0;
- return ;
- break;
case RQ_ASIS:
p->target = cnode;
return ;
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index e124fc7952..e9d1fc30d4 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -1196,6 +1196,20 @@ class TestRegexp < Test::Unit::TestCase
}
end
+ def test_quantifier_reduction
+ assert_equal('aa', eval('/(a+?)*/').match('aa')[0])
+ assert_equal('aa', eval('/(?:a+?)*/').match('aa')[0])
+
+ quantifiers = %w'? * + ?? *? +?'
+ quantifiers.each do |q1|
+ quantifiers.each do |q2|
+ r1 = eval("/(a#{q1})#{q2}/").match('aa')[0]
+ r2 = eval("/(?:a#{q1})#{q2}/").match('aa')[0]
+ assert_equal(r1, r2)
+ end
+ end
+ end
+
def test_once
pr1 = proc{|i| /#{i}/o}
assert_equal(/0/, pr1.call(0))