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 #31145

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 0a6626ce332ae3ad3e49cb99404646c22c866b71..9c28520ed56998173c105b9d8a2ca3c4489b916e 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

##############################################################################
@@ -670,6 +673,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 dc5e2ea50898fbf684f5f4655d8b50982d4ebbbd..f7cbc54499464acf1a7de45251a6118340ec51fd 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -21734,10 +21734,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 27204f7f519229cc4c21a10dd0a44222d4b6edd6..2692748e623d3d52780ff89a97f4300bcd981cbd 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -2346,6 +2346,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