Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: crash in v8 due to regexp reentrancy #31144

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions patches/v8/.patches
Expand Up @@ -7,3 +7,6 @@ do_not_export_private_v8_symbols_on_windows.patch
fix_build_deprecated_attirbute_for_older_msvc_versions.patch
fix_disable_implies_dcheck_for_node_stream_array_buffers.patch
cppgc-js_support_eager_traced_value_in_ephemeron_pairs.patch
regexp_add_a_currently_failing_cctest_for_irregexp_reentrancy.patch
regexp_allow_reentrant_irregexp_execution.patch
regexp_remove_the_stack_parameter_from_regexp_matchers.patch
@@ -0,0 +1,109 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jakob Gruber <jgruber@chromium.org>
Date: Mon, 6 Sep 2021 08:29:33 +0200
Subject: Add a (currently failing) cctest for irregexp reentrancy

The test should be enabled once reentrancy is supported.

Bug: v8:11382
Change-Id: Ifb90d8a6fd8bf9f05e9ca2405d4e04e013ce7ee3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3138201
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Patrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76667}

diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 9b369044754443ccf5ce07c3612f0a928e565ad6..21afa5310647eb67f3fe3fc4f2e0721b4bb4e0f6 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -136,6 +136,9 @@
'test-strings/Traverse': [PASS, HEAVY],
'test-swiss-name-dictionary-csa/DeleteAtBoundaries': [PASS, HEAVY],
'test-swiss-name-dictionary-csa/SameH2': [PASS, HEAVY],
+
+ # TODO(v8:11382): Reenable once irregexp is reentrant.
+ 'test-regexp/RegExpInterruptReentrantExecution': [FAIL],
}], # ALWAYS

##############################################################################
@@ -666,6 +669,9 @@

# Instruction cache flushing is disabled in jitless mode.
'test-icache/*': [SKIP],
+
+ # Tests generated irregexp code.
+ 'test-regexp/RegExpInterruptReentrantExecution': [SKIP],
}], # lite_mode or variant == jitless

##############################################################################
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 25fba193bbcc41d127d36949e103cb59688bfed7..b21222f14c533cb630946b6066bfe24d1be49f93 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -21658,10 +21658,6 @@ TEST(RegExpInterruptAndMakeSubjectTwoByteExternal) {
// experimental engine.
i::FLAG_enable_experimental_regexp_engine_on_excessive_backtracks = false;
RegExpInterruptTest test;
- // We want to be stuck regexp execution, so no fallback to linear-time
- // engine.
- // TODO(mbid,v8:10765): Find a way to test interrupt support of the
- // experimental engine.
test.RunTest(RegExpInterruptTest::MakeSubjectTwoByteExternal);
}

diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index aa24fe3dd230ecc06d9eea2920826dc123979c58..2fb5b3d056f78d3eef3a0a1032ee99df1b2f35c5 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -2348,6 +2348,50 @@ TEST(UnicodePropertyEscapeCodeSize) {
}
}

+namespace {
+
+struct RegExpExecData {
+ i::Isolate* isolate;
+ i::Handle<i::JSRegExp> regexp;
+ i::Handle<i::String> subject;
+};
+
+i::Handle<i::Object> RegExpExec(const RegExpExecData* d) {
+ return i::RegExp::Exec(d->isolate, d->regexp, d->subject, 0,
+ d->isolate->regexp_last_match_info())
+ .ToHandleChecked();
+}
+
+void ReenterRegExp(v8::Isolate* isolate, void* data) {
+ RegExpExecData* d = static_cast<RegExpExecData*>(data);
+ i::Handle<i::Object> result = RegExpExec(d);
+ CHECK(result->IsNull());
+}
+
+} // namespace
+
+// Tests reentrant irregexp calls.
+TEST(RegExpInterruptReentrantExecution) {
+ CHECK(!i::FLAG_jitless);
+ i::FLAG_regexp_tier_up = false; // Enter irregexp, not the interpreter.
+
+ LocalContext context;
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ RegExpExecData d;
+ d.isolate = reinterpret_cast<i::Isolate*>(isolate);
+ d.regexp = v8::Utils::OpenHandle(
+ *v8::RegExp::New(context.local(), v8_str("(a*)*x"), v8::RegExp::kNone)
+ .ToLocalChecked());
+ d.subject = v8::Utils::OpenHandle(*v8_str("aaaa"));
+
+ isolate->RequestInterrupt(&ReenterRegExp, &d);
+
+ i::Handle<i::Object> result = RegExpExec(&d);
+ CHECK(result->IsNull());
+}
+
#undef CHECK_PARSE_ERROR
#undef CHECK_SIMPLE
#undef CHECK_MIN_MAX