aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTSUYUSATO Kitsune <make.just.on@gmail.com>2023-03-13 15:46:41 +0900
committerGitHub <noreply@github.com>2023-03-13 15:46:41 +0900
commite22c4e8877677ff90805e4a4dcbdef80f4220136 (patch)
treecdfd0c7168e8ef682454715408baa84d6ded5b06
parented269c81aa68ba87e9da2fe4c0c2227ea0689eca (diff)
downloadruby-e22c4e8877677ff90805e4a4dcbdef80f4220136.tar.gz
[Bug #19467] correct cache points and counting failure on `OP_ANYCHAR_STAR_PEEK_NEXT` (#7454)
-rw-r--r--regexec.c20
-rw-r--r--test/ruby/test_regexp.rb10
2 files changed, 26 insertions, 4 deletions
diff --git a/regexec.c b/regexec.c
index d261a3cbc0..5f454ac8ef 100644
--- a/regexec.c
+++ b/regexec.c
@@ -2835,10 +2835,16 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_STAR_PEEK_NEXT) MOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);
while (DATA_ENSURE_CHECK1) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, end - s, msa->match_cache);
if (*p == *s) {
- DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, end - s, msa->match_cache);
STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
- }
+ } else {
+ /* We need to increment num_fail here, for invoking a cache optimization correctly. */
+ /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR` simply in this case.*/
+#ifdef USE_CACHE_MATCH_OPT
+ msa->num_fail++;
+#endif
+ }
n = enclen(encode, s, end);
DATA_ENSURE(n);
if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
@@ -2851,10 +2857,16 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_ML_STAR_PEEK_NEXT)MOP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);
while (DATA_ENSURE_CHECK1) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
if (*p == *s) {
- DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
- }
+ } else {
+ /* We need to increment num_fail here, for invoking a cache optimization correctly. */
+ /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR_ML` simply in this case.*/
+#ifdef USE_CACHE_MATCH_OPT
+ msa->num_fail++;
+#endif
+ }
n = enclen(encode, s, end);
if (n > 1) {
DATA_ENSURE(n);
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index ae2bf82bb8..2fc418d96f 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -1755,6 +1755,16 @@ class TestRegexp < Test::Unit::TestCase
assert_equal("10:0:0".match(pattern)[0], "10:0:0")
end
+ def test_bug_19467
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+
+ assert_nil(/\A.*a.*z\z/ =~ "a" * 1000000 + "y")
+ end;
+ end
+
def test_linear_time_p
assert_send [Regexp, :linear_time?, /a/]
assert_send [Regexp, :linear_time?, 'a']