Skip to content

Commit 96ee9bb

Browse files
legendecasV8 LUCI CQ
authored andcommitted
[snapshot] Check if a cached data has wrapped arguments
Fixes that ScriptCompiler::CreateCodeCacheForFunction aborts on a deserialized shared function info from a cached data accepted with ScriptCompiler::CompileFunction. If the wrapped argument list does not match, the cached data should be rejected. Refs: nodejs/node#56366 Change-Id: I3f0376216791d866fac8eed1ce88dfa05e919b48 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6140933 Commit-Queue: Chengzhong Wu <[email protected]> Reviewed-by: Leszek Swirski <[email protected]> Cr-Commit-Position: refs/heads/main@{#97942}
1 parent b64f4ed commit 96ee9bb

3 files changed

Lines changed: 94 additions & 7 deletions

File tree

src/snapshot/code-serializer.cc

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,16 @@ ScriptCompiler::CachedData* CodeSerializer::Serialize(
7171

7272
// Serialize code object.
7373
DirectHandle<String> source(Cast<String>(script->source()), isolate);
74+
DirectHandle<FixedArray> wrapped_arguments;
75+
if (script->is_wrapped()) {
76+
wrapped_arguments =
77+
DirectHandle<FixedArray>(script->wrapped_arguments(), isolate);
78+
}
79+
7480
HandleScope scope(isolate);
75-
CodeSerializer cs(isolate, SerializedCodeData::SourceHash(
76-
source, script->origin_options()));
81+
CodeSerializer cs(isolate,
82+
SerializedCodeData::SourceHash(source, wrapped_arguments,
83+
script->origin_options()));
7784
DisallowGarbageCollection no_gc;
7885

7986
#ifndef DEBUG
@@ -489,11 +496,17 @@ MaybeDirectHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
489496

490497
HandleScope scope(isolate);
491498

499+
DirectHandle<FixedArray> wrapped_arguments;
500+
if (!script_details.wrapped_arguments.is_null()) {
501+
wrapped_arguments = script_details.wrapped_arguments.ToHandleChecked();
502+
}
503+
492504
SerializedCodeSanityCheckResult sanity_check_result =
493505
SerializedCodeSanityCheckResult::kSuccess;
494506
const SerializedCodeData scd = SerializedCodeData::FromCachedData(
495507
isolate, cached_data,
496-
SerializedCodeData::SourceHash(source, script_details.origin_options),
508+
SerializedCodeData::SourceHash(source, wrapped_arguments,
509+
script_details.origin_options),
497510
&sanity_check_result);
498511
if (sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) {
499512
if (v8_flags.profile_deserialization) {
@@ -604,6 +617,11 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::FinishOffThreadDeserialize(
604617

605618
HandleScope scope(isolate);
606619

620+
DirectHandle<FixedArray> wrapped_arguments;
621+
if (!script_details.wrapped_arguments.is_null()) {
622+
wrapped_arguments = script_details.wrapped_arguments.ToHandleChecked();
623+
}
624+
607625
// Do a source sanity check now that we have the source. It's important for
608626
// FromPartiallySanityCheckedCachedData call that the sanity_check_result
609627
// holds the result of the off-thread sanity check.
@@ -612,7 +630,8 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::FinishOffThreadDeserialize(
612630
const SerializedCodeData scd =
613631
SerializedCodeData::FromPartiallySanityCheckedCachedData(
614632
cached_data,
615-
SerializedCodeData::SourceHash(source, script_details.origin_options),
633+
SerializedCodeData::SourceHash(source, wrapped_arguments,
634+
script_details.origin_options),
616635
&sanity_check_result);
617636
if (sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) {
618637
// The only case where the deserialization result could exist despite a
@@ -793,15 +812,17 @@ SerializedCodeSanityCheckResult SerializedCodeData::SanityCheckWithoutSource(
793812
return SerializedCodeSanityCheckResult::kSuccess;
794813
}
795814

796-
uint32_t SerializedCodeData::SourceHash(DirectHandle<String> source,
797-
ScriptOriginOptions origin_options) {
815+
uint32_t SerializedCodeData::SourceHash(
816+
DirectHandle<String> source, DirectHandle<FixedArray> wrapped_arguments,
817+
ScriptOriginOptions origin_options) {
798818
const uint32_t source_length = source->length();
819+
const uint32_t has_wrapped_arguments = !wrapped_arguments.is_null();
799820

800821
static constexpr uint32_t kModuleFlagMask = (1 << 31);
801822
const uint32_t is_module = origin_options.IsModule() ? kModuleFlagMask : 0;
802823
DCHECK_EQ(0, source_length & kModuleFlagMask);
803824

804-
return source_length | is_module;
825+
return source_length | is_module | has_wrapped_arguments << 1;
805826
}
806827

807828
// Return ScriptData object and relinquish ownership over it to the caller.

src/snapshot/code-serializer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ class SerializedCodeData : public SerializedData {
153153
base::Vector<const uint8_t> Payload() const;
154154

155155
static uint32_t SourceHash(DirectHandle<String> source,
156+
DirectHandle<FixedArray> wrapped_arguments,
156157
ScriptOriginOptions origin_options);
157158

158159
private:

test/cctest/test-serialize.cc

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6202,6 +6202,71 @@ TEST(CachedCompileFunction) {
62026202
}
62036203
}
62046204

6205+
TEST(InvalidCachedCompileFunction) {
6206+
DisableAlwaysOpt();
6207+
LocalContext env;
6208+
Isolate* isolate = CcTest::i_isolate();
6209+
isolate->compilation_cache()
6210+
->DisableScriptAndEval(); // Disable same-isolate code cache.
6211+
6212+
v8::HandleScope scope(CcTest::isolate());
6213+
6214+
v8::Local<v8::String> source = v8_str("");
6215+
ScriptCompiler::CachedData* script_cache;
6216+
{
6217+
v8::ScriptCompiler::Source script_source(source);
6218+
v8::Local<v8::UnboundScript> script =
6219+
v8::ScriptCompiler::CompileUnboundScript(
6220+
reinterpret_cast<v8::Isolate*>(isolate), &script_source,
6221+
v8::ScriptCompiler::kEagerCompile)
6222+
.ToLocalChecked();
6223+
script_cache = v8::ScriptCompiler::CreateCodeCache(script);
6224+
}
6225+
6226+
ScriptCompiler::CachedData* fun_cache;
6227+
{
6228+
v8::ScriptCompiler::Source script_source(source, script_cache);
6229+
v8::Local<v8::Function> fun =
6230+
v8::ScriptCompiler::CompileFunction(
6231+
env.local(), &script_source, 0, nullptr, 0, nullptr,
6232+
v8::ScriptCompiler::kConsumeCodeCache)
6233+
.ToLocalChecked();
6234+
// Check that the cached data can be re-created.
6235+
fun_cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun);
6236+
// Check that the cached data without wrapped arguments is rejected.
6237+
CHECK(script_source.GetCachedData()->rejected);
6238+
}
6239+
6240+
{
6241+
DisallowCompilation no_compile_expected(isolate);
6242+
v8::ScriptCompiler::Source script_source(source, fun_cache);
6243+
v8::Local<v8::Function> fun =
6244+
v8::ScriptCompiler::CompileFunction(
6245+
env.local(), &script_source, 0, nullptr, 0, nullptr,
6246+
v8::ScriptCompiler::kConsumeCodeCache)
6247+
.ToLocalChecked();
6248+
v8::Local<v8::Value> result =
6249+
fun->Call(env.local(), v8::Undefined(CcTest::isolate()), 0, nullptr)
6250+
.ToLocalChecked();
6251+
CHECK(result->IsUndefined());
6252+
fun_cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun);
6253+
}
6254+
6255+
{
6256+
v8::ScriptCompiler::Source script_source(source, fun_cache);
6257+
v8::Local<v8::UnboundScript> script =
6258+
v8::ScriptCompiler::CompileUnboundScript(
6259+
reinterpret_cast<v8::Isolate*>(isolate), &script_source,
6260+
v8::ScriptCompiler::kConsumeCodeCache)
6261+
.ToLocalChecked();
6262+
// Check that the cached data can be re-created.
6263+
script_cache = v8::ScriptCompiler::CreateCodeCache(script);
6264+
// Check that the cached data with wrapped arguments is rejected.
6265+
CHECK(script_source.GetCachedData()->rejected);
6266+
delete script_cache;
6267+
}
6268+
}
6269+
62056270
TEST(CachedCompileFunctionRespectsEager) {
62066271
DisableAlwaysOpt();
62076272
LocalContext env;

0 commit comments

Comments
 (0)