Chrome · V8 › Deserializer
CVE-2026-110919
UAF in V8 (Deserializer)
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifsrc/snapshot/code-serializer.cc |
modified | |
CodeSerializersrc/snapshot/code-serializer.h |
modified | |
SerializedCodeDatasrc/snapshot/code-serializer.h |
modified | |
TEST_Ftest/unittests/api/deserialize-unittest.cc |
modified |
Files Changed
test/unittests/api/deserialize-unittest.ccsrc/codegen/compiler.ccsrc/snapshot/code-serializer.hsrc/codegen/compiler.hsrc/snapshot/code-serializer.cc
Patch
From 9d9ccafe3b95e4658806c1d7514257d6042a1ba4 Mon Sep 17 00:00:00 2001
From: Leszek Swirski <leszeks@chromium.org>
Date: Wed, 07 Oct 2026 16:52:46 +0200
Subject: [PATCH] [deserializer] Check source hash before starting BG merge
Off-thread code cache deserialization happens before source text is
available, so we can't verify the cache's source hash up front. When
source text becomes available, SourceTextAvailable previously set up a
background merge with a matching Script from the compilation cache
without checking whether the serialized code cache's source hash
(including module vs. classic origin options) matched the incoming
script. If a module code cache was handed to a classic script load of
the same URL, the background merge would merge incompatible scripts
before FinishOffThreadDeserialize rejected the cache.
Check the cached data's source hash via
CodeSerializer::NotifySourceTextAvailable before setting up the
background merge task, and record the result in
OffThreadDeserializeData::source_sanity_check_result so
FinishOffThreadDeserialize does not recompute it. Populate
OffThreadDeserializeData in-place in StartDeserializeOffThread and avoid
reading data->sanity_check_result or mutating cached_data->Reject() in
NotifySourceTextAvailable so the main-thread source check cannot race
with or be clobbered by concurrent background deserialization.
TAG=agy
CONV=d5ba0f6d-8783-4ff9-b6c1-1b9dffa490f4
Fixed: 568831769
Change-Id: Id8d350af7ef0a4f52fb954ad16902b1cfab364ea
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8526067
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#110449}
---
diff --git a/src/codegen/compiler.cc b/src/codegen/compiler.cc
index 6e4bf13..d1b2bec 100644
--- a/src/codegen/compiler.cc
+++ b/src/codegen/compiler.cc
@@ -2875,8 +2875,8 @@
LocalHandleScope handle_scope(&isolate);
DirectHandle<SharedFunctionInfo> inner_result;
- off_thread_data_ =
- CodeSerializer::StartDeserializeOffThread(&isolate, &cached_data_);
+ CodeSerializer::StartDeserializeOffThread(&isolate, &cached_data_,
+ &off_thread_data_);
if (off_thread_data_.HasResult()) {
Tagged<Script> script = *off_thread_data_.GetOnlyScript(isolate.heap());
script_type_timer.set_histogram(
@@ -2898,6 +2898,11 @@
Isolate* isolate, Handle<String> source_text,
const ScriptDetails& script_details) {
DCHECK_EQ(isolate, isolate_for_local_isolate_);
+ if (!CodeSerializer::NotifySourceTextAvailable(isolate, &off_thread_data_,
+ &cached_data_, source_text,
+ script_details)) {
+ return;
+ }
LanguageMode language_mode = construct_language_mode(v8_flags.use_strict);
background_merge_task_.SetUpOnMainThread(isolate, source_text, script_details,
language_mode);
diff --git a/src/codegen/compiler.h b/src/codegen/compiler.h
index af0057d..003b30a 100644
--- a/src/codegen/compiler.h
+++ b/src/codegen/compiler.h
@@ -722,7 +722,7 @@
private:
Isolate* isolate_for_local_isolate_;
AlignedCachedData cached_data_;
- CodeSerializer::OffThreadDeserializeData off_thread_data_;
+ OffThreadDeserializeData off_thread_data_;
BackgroundMergeTask background_merge_task_;
TimedHistogram* timer_;
int64_t background_time_in_microseconds_ = 0;
diff --git a/src/snapshot/code-serializer.cc b/src/snapshot/code-serializer.cc
index 9dcff86..e1bfe5d 100644
--- a/src/snapshot/code-serializer.cc
+++ b/src/snapshot/code-serializer.cc
@@ -346,8 +346,8 @@
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&local_isolate);
LocalHandleScope handle_scope(&local_isolate);
- off_thread_data_ =
- CodeSerializer::StartDeserializeOffThread(&local_isolate, cached_data_);
+ CodeSerializer::StartDeserializeOffThread(&local_isolate, cached_data_,
+ &off_thread_data_);
}
MaybeDirectHandle<SharedFunctionInfo> Finalize(
@@ -361,7 +361,7 @@
private:
Isolate* isolate_;
AlignedCachedData* cached_data_;
- CodeSerializer::OffThreadDeserializeData off_thread_data_;
+ OffThreadDeserializeData off_thread_data_;
};
void FinalizeDeserialization(Isolate* isolate,
@@ -555,8 +555,7 @@
return scope.CloseAndEscape(result);
}
-DirectHandle<Script> CodeSerializer::OffThreadDeserializeData::GetOnlyScript(
- LocalHeap* heap) {
+DirectHandle<Script> OffThreadDeserializeData::GetOnlyScript(LocalHeap* heap) {
std::unique_ptr<PersistentHandles> previous_persistent_handles =
heap->DetachPersistentHandles();
heap->AttachPersistentHandles(std::move(persistent_handles));
@@ -574,32 +573,47 @@
return script;
}
-CodeSerializer::OffThreadDeserializeData
-CodeSerializer::StartDeserializeOffThread(LocalIsolate* local_isolate,
- AlignedCachedData* cached_data) {
- OffThreadDeserializeData result;
-
+void CodeSerializer::StartDeserializeOffThread(LocalIsolate* local_isolate,
+ AlignedCachedData* cached_data,
+ OffThreadDeserializeData* data) {
DCHECK(!local_isolate->heap()->HasPersistentHandles());
const SerializedCodeData scd =
SerializedCodeData::FromCachedDataWithoutSource(
- local_isolate, cached_data, &result.sanity_check_result);
- if (result.sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) {
+ local_isolate, cached_data, &data->sanity_check_result);
+ if (data->sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) {
// Exit early but don't report yet, we'll re-check this when finishing on
// the main thread
DCHECK(cached_data->rejected());
- return result;
+ return;
}
MaybeDirectHandle<SharedFunctionInfo> local_maybe_result =
OffThreadObjectDeserializer::DeserializeSharedFunctionInfo(
- local_isolate, &scd, &result.scripts);
+ local_isolate, &scd, &data->scripts);
- result.maybe_result =
+ data->maybe_result =
local_isolate->heap()->NewPersistentMaybeHandle(local_maybe_result);
- result.persistent_handles = local_isolate->heap()->DetachPersistentHandles();
+ data->persistent_handles = local_isolate->heap()->DetachPersistentHandles();
+}
- return result;
+bool CodeSerializer::NotifySourceTextAvailable(
+ Isolate* isolate, OffThreadDeserializeData* data,
+ const AlignedCachedData* cached_data, DirectHandle<String> source,
+ const ScriptDetails& script_details) {
+ HandleScope scope(isolate);
+
+ // Only check the source hash against the immutable cached_data header and
+ // write the main-thread-only data->source_sanity_check_result field here. Do
+ // not read/write data->sanity_check_result or mutate cached_data->Reject(),
+ // as StartDeserializeOffThread may still be running concurrently on a
+ // background thread. Full rejection and histogram reporting happen in
+ // FinishOffThreadDeserialize.
+ SerializedCodeData scd(cached_data);
+ SerializedCodeSanityCheckResult sanity_check_result =
+ scd.SanityCheckJustSource(isolate, source, script_details);
+ data->source_sanity_check_result = sanity_check_result;
+ return sanity_check_result == SerializedCodeSanityCheckResult::kSuccess;
}
MaybeDirectHandle<SharedFunctionInfo>
@@ -615,11 +629,6 @@
HandleScope scope(isolate);
- DirectHandle<FixedArray> wrapped_arguments;
- if (!script_details.wrapped_arguments.is_null()) {
- wrapped_arguments = script_details.wrapped_arguments.ToHandleChecked();
- }
-
// Do a source sanity check now that we have the source. It's important for
// FromPartiallySanityCheckedCachedData call that the sanity_check_result
// holds the result of the off-thread sanity check.
@@ -627,11 +636,9 @@
data.sanity_check_result;
const SerializedCodeData scd =
SerializedCodeData::FromPartiallySanityCheckedCachedData(
- cached_data,
- SerializedCodeData::SourceHash(source, wrapped_arguments,
- script_details.origin_options,
- isolate),
+ isolate, cached_data, data, source, script_details,
&sanity_check_result);
+ USE(scd);
if (sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) {
// The only case where the deserialization result could exist despite a
// check failure is on a source mismatch, since we can't test for this
@@ -773,6 +780,17 @@
}
SerializedCodeSanityCheckResult SerializedCodeData::SanityCheckJustSource(
+ Isolate* isolate, DirectHandle<String> source,
+ const ScriptDetails& script_details) const {
+ DirectHandle<FixedArray> wrapped_arguments;
+ if (!script_details.wrapped_arguments.is_null()) {
+ wrapped_arguments = script_details.wrapped_arguments.ToHandleChecked();
+ }
+ return SanityCheckJustSource(SourceHash(
+ source, wrapped_arguments, script_details.origin_options, isolate));
+}
+
+SerializedCodeSanityCheckResult SerializedCodeData::SanityCheckJustSource(
SourceHash expected_source_hash) const {
if (size_ < kHeaderSize) {
return SerializedCodeSanityCheckResult::kInvalidHeader;
@@ -918,7 +936,7 @@
return base::Vector<const uint8_t>(payload, length);
}
-SerializedCodeData::SerializedCodeData(AlignedCachedData* data)
+SerializedCodeData::SerializedCodeData(const AlignedCachedData* data)
: SerializedData(const_cast<uint8_t*>(data->data()), data->length()) {}
SerializedCodeData SerializedCodeData::FromCachedData(
@@ -953,12 +971,14 @@
}
SerializedCodeData SerializedCodeData::FromPartiallySanityCheckedCachedData(
- AlignedCachedData* cached_data, SourceHash expected_source_hash,
+ Isolate* isolate, AlignedCachedData* cached_data,
+ const OffThreadDeserializeData& data, DirectHandle<String> source,
+ const ScriptDetails& script_details,
SerializedCodeSanityCheckResult* rejection_result) {
- DisallowGarbageCollection no_gc;
// The previous call to FromCachedDataWithoutSource may have already rejected
// the cached data, so reuse the previous rejection result if it's not a
// success.
+ *rejection_result = data.sanity_check_result;
if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) {
// FromCachedDataWithoutSource doesn't check the source, so there can't be
// a source mismatch.
@@ -968,7 +988,14 @@
return SerializedCodeData(nullptr, 0);
}
SerializedCodeData scd(cached_data);
- *rejection_result = scd.SanityCheckJustSource(expected_source_hash);
+ if (data.source_sanity_check_result.has_value()) {
+ DCHECK_EQ(*data.source_sanity_check_result,
+ scd.SanityCheckJustSource(isolate, source, script_details));
+ *rejection_result = *data.source_sanity_check_result;
+ } else {
+ *rejection_result =
+ scd.SanityCheckJustSource(isolate, source, script_details);
+ }
if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) {
// This check only checks the source, so the only possible failure is a
// source mismatch.
diff --git a/src/snapshot/code-serializer.h b/src/snapshot/code-serializer.h
index 2caad19..315751a 100644
--- a/src/snapshot/code-serializer.h
+++ b/src/snapshot/code-serializer.h
@@ -6,6 +6,7 @@
#define V8_SNAPSHOT_CODE_SERIALIZER_H_
#include <array>
+#include <optional>
#include "src/base/macros.h"
#include "src/codegen/script-details.h"
@@ -62,6 +63,22 @@
class CodeSerializer;
+struct OffThreadDeserializeData {
+ public:
+ bool HasResult() const { return !maybe_result.is_null(); }
+ DirectHandle<Script> GetOnlyScript(LocalHeap* heap);
+
+ private:
+ friend class CodeSerializer;
+ friend class SerializedCodeData;
+ MaybeIndirectHandle<SharedFunctionInfo> maybe_result;
+ std::vector<IndirectHandle<Script>> scripts;
+ std::unique_ptr<PersistentHandles> persistent_handles;
+ SerializedCodeSanityCheckResult sanity_check_result =
+ SerializedCodeSanityCheckResult::kSuccess;
+ std::optional<SerializedCodeSanityCheckResult> source_sanity_check_result;
+};
+
// Wrapper around ScriptData to provide code-serializer-specific functionality.
class SerializedCodeData : public SerializedData {
public:
@@ -122,7 +139,9 @@
// FromCachedDataWithoutSource. The rejection result from that call should be
// passed into this one.
static SerializedCodeData FromPartiallySanityCheckedCachedData(
- AlignedCachedData* cached_data, SourceHash expected_source_hash,
+ Isolate* isolate, AlignedCachedData* cached_data,
+ const OffThreadDeserializeData& data, DirectHandle<String> source,
+ const ScriptDetails& script_details,
SerializedCodeSanityCheckResult* rejection_result);
// Used when producing.
@@ -135,7 +154,8 @@
base::Vector<const uint8_t> Payload() const;
private:
- explicit SerializedCodeData(AlignedCachedData* data);
+ friend class CodeSerializer;
+ explicit SerializedCodeData(const AlignedCachedData* data);
SerializedCodeData(const uint8_t* data, int size)
: SerializedData(const_cast<uint8_t*>(data), size) {}
@@ -151,6 +171,9 @@
uint32_t expected_ro_snapshot_checksum,
SourceHash expected_source_hash) const;
SerializedCodeSanityCheckResult SanityCheckJustSource(
+ Isolate* isolate, DirectHandle<String> source,
+ const ScriptDetails& script_details) const;
+ SerializedCodeSanityCheckResult SanityCheckJustSource(
SourceHash expected_source_hash) const;
SerializedCodeSanityCheckResult SanityCheckWithoutSource(
uint32_t expected_ro_snapshot_checksum) const;
@@ -160,19 +183,6 @@
public:
using SourceHash = SerializedCodeData::SourceHash;
- struct OffThreadDeserializeData {
- public:
- bool HasResult() const { return !maybe_result.is_null(); }
- DirectHandle<Script> GetOnlyScript(LocalHeap* heap);
-
- private:
- friend class CodeSerializer;
- MaybeIndirectHandle<SharedFunctionInfo> maybe_result;
- std::vector<IndirectHandle<Script>> scripts;
- std::unique_ptr<PersistentHandles> persistent_handles;
- SerializedCodeSanityCheckResult sanity_check_result;
- };
-
CodeSerializer(const CodeSerializer&) = delete;
CodeSerializer& operator=(const CodeSerializer&) = delete;
V8_EXPORT_PRIVATE static ScriptCompiler::CachedData* Serialize(
@@ -186,9 +196,14 @@
DirectHandle<String> source, const ScriptDetails& script_details,
MaybeDirectHandle<Script> maybe_cached_script = {});
- V8_WARN_UNUSED_RESULT static OffThreadDeserializeData
- StartDeserializeOffThread(LocalIsolate* isolate,
- AlignedCachedData* cached_data);
+ static void StartDeserializeOffThread(LocalIsolate* isolate,
+ AlignedCachedData* cached_data,
+ OffThreadDeserializeData* data);
+
+ V8_WARN_UNUSED_RESULT static bool NotifySourceTextAvailable(
+ Isolate* isolate, OffThreadDeserializeData* data,
+ const AlignedCachedData* cached_data, DirectHandle<String> source,
+ const ScriptDetails& script_details);
V8_WARN_UNUSED_RESULT static MaybeDirectHandle<SharedFunctionInfo>
FinishOffThreadDeserialize(
diff --git a/test/unittests/api/deserialize-unittest.cc b/test/unittests/api/deserialize-unittest.cc
index ecd607e..fb9fb99 100644
--- a/test/unittests/api/deserialize-unittest.cc
+++ b/test/unittests/api/deserialize-unittest.cc
@@ -1333,4 +1333,148 @@
}
}
+TEST_F(MergeDeserializedCodeTest, ModuleCacheClassicScriptMismatch) {
+ i::v8_flags.merge_background_deserialized_script_with_compilation_cache =
+ true;
+ std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data;
+ IsolateAndContextScope scope(this);
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate());
+ PersistentScriptOrigin default_origin(
+ isolate(), NewString("http://example.com/test.js"));
+
+ constexpr char kPolyglotSource[] =
+ "let L0 = 1;\n"
+ "var z, o;\n"
+ "function g() { throw 1; }\n"
+ "function K(a, b) { var t = globalThis.top; (t.__keep = t.__keep || "
+ "[]).push(a, b); }\n"
+ "z = await /1; function lazyOuter() { function inner() {} } { try { g() "
+ "} catch /* 1, o = { a: function () {}, 'NAMENAMENAMENAME' //*/\n"
+ "(e) { K(() => e, function later() { return e }) } }\n";
+
+ // Setup: define `await` and `top` in global scope for classic script parse.
+ {
+ v8::HandleScope handle_scope(isolate());
+ Local<Script> setup =
+ Script::Compile(
+ context(), NewString("var await = 6; globalThis.top = globalThis;"))
+ .ToLocalChecked();
+ CHECK(!setup->Run(context()).IsEmpty());
+ }
+
+ // Step 1: Compile and run as a classic script, populating the Isolate
+ // compilation cache and retaining catch-block closures in globalThis.__keep.
+ // Also compile as a module with the same resource name and create a module
... (file diff truncated)
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/test/unittests/api/deserialize-unittest.cc b/test/unittests/api/deserialize-unittest.cc
index ecd607e..fb9fb99 100644
--- a/test/unittests/api/deserialize-unittest.cc
+++ b/test/unittests/api/deserialize-unittest.cc
@@ -1333,4 +1333,148 @@
}
}
+TEST_F(MergeDeserializedCodeTest, ModuleCacheClassicScriptMismatch) {
+ i::v8_flags.merge_background_deserialized_script_with_compilation_cache =
+ true;
+ std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data;
+ IsolateAndContextScope scope(this);
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate());
+ PersistentScriptOrigin default_origin(
+ isolate(), NewString("http://example.com/test.js"));
+
+ constexpr char kPolyglotSource[] =
+ "let L0 = 1;\n"
+ "var z, o;\n"
+ "function g() { throw 1; }\n"
+ "function K(a, b) { var t = globalThis.top; (t.__keep = t.__keep || "
+ "[]).push(a, b); }\n"
+ "z = await /1; function lazyOuter() { function inner() {} } { try { g() "
+ "} catch /* 1, o = { a: function () {}, 'NAMENAMENAMENAME' //*/\n"
+ "(e) { K(() => e, function later() { return e }) } }\n";
+
+ // Setup: define `await` and `top` in global scope for classic script parse.
+ {
+ v8::HandleScope handle_scope(isolate());
+ Local<Script> setup =
+ Script::Compile(
+ context(), NewString("var await = 6; globalThis.top = globalThis;"))
+ .ToLocalChecked();
+ CHECK(!setup->Run(context()).IsEmpty());
+ }
+
+ // Step 1: Compile and run as a classic script, populating the Isolate
+ // compilation cache and retaining catch-block closures in globalThis.__keep.
+ // Also compile as a module with the same resource name and create a module
+ // code cache, then age and flush the classic script's top-level bytecode.
+ {
+ v8::HandleScope handle_scope(isolate());
+ ScriptOrigin classic_origin = default_origin.AsScriptOrigin();
+ Local<Script> script =
+ Script::Compile(context(), NewString(kPolyglotSource), &classic_origin)
+ .ToLocalChecked();
+ CHECK(!script->Run(context()).IsEmpty());
+
+ ScriptOrigin module_origin(NewString("http://example.com/test.js"), 0, 0,
+ false, -1, Local<Value>(), false, false,
+ /*is_module=*/true);
+ ScriptCompiler::Source module_source(NewString(kPolyglotSource),
+ module_origin);
+ Local<Module> module =
+ ScriptCompiler::CompileModule(isolate(), &module_source)
+ .ToLocalChecked();
+ cached_data.reset(
+ ScriptCompiler::CreateCodeCache(module->GetUnboundModuleScript()));
+
+ i::SharedFunctionInfo::EnsureOldForTesting(GetSharedFunctionInfo(script));
+ }
+
+ // Step 2: Flush the classic script's top-level bytecode via major GC.
+ {
+ i::DisableConservativeStackScanningScopeForTesting no_css_scope(
+ i_isolate->heap());
+ InvokeMajorGC(i_isolate);
+ InvokeMajorGC(i_isolate);
+ }
+
+ // Step 3a: Start off-thread consumption of the MODULE code cache, then notify
+ // SourceTextAvailable with the CLASSIC ScriptOrigin after Run() completes.
+ {
+ auto task_cached_data = std::make_unique<ScriptCompiler::CachedData>(
+ cached_data->data, cached_data->length,
+ ScriptCompiler::CachedData::BufferNotOwned);
+ DeserializeThread deserialize_thread(
+ ScriptCompiler::StartConsumingCodeCache(
+ isolate(), std::make_unique<ScriptCompiler::CachedData>(
+ cached_data->data, cached_data->length,
+ ScriptCompiler::CachedData::BufferNotOwned)));
+ CHECK(deserialize_thread.Start());
+ deserialize_thread.Join();
+
+ std::unique_ptr<ScriptCompiler::ConsumeCodeCacheTask> task =
+ deserialize_thread.TakeTask();
+ task->SourceTextAvailable(isolate(), NewString(kPolyglotSource),
+ default_origin.AsScriptOrigin());
+ CHECK(!task->ShouldMergeWithExistingScript());
+
+ v8::HandleScope handle_scope(isolate());
+ ScriptCompiler::Source source(NewString(kPolyglotSource),
+ default_origin.AsScriptOrigin(),
+ task_cached_data.release(), task.release());
+ Local<Script> script =
+ ScriptCompiler::Compile(context(), &source,
+ ScriptCompiler::kConsumeCodeCache)
+ .ToLocalChecked();
+ CHECK(!script.IsEmpty());
+ CHECK(source.GetCachedData()->rejected);
+
+ // Age and flush the recompiled classic script's top-level bytecode again so
+ // Step 3b also sees a flushed Script in the Isolate compilation cache.
+ i::SharedFunctionInfo::EnsureOldForTesting(GetSharedFunctionInfo(script));
+ }
+ {
+ i::DisableConservativeStackScanningScopeForTesting no_css_scope(
+ i_isolate->heap());
+ InvokeMajorGC(i_isolate);
+ InvokeMajorGC(i_isolate);
+ }
+
+ // Step 3b: Also test calling SourceTextAvailable on the main thread BEFORE
+ // Run() executes on the background thread.
+ {
+ auto task_cached_data = std::make_unique<ScriptCompiler::CachedData>(
+ cached_data->data, cached_data->length,
+ ScriptCompiler::CachedData::BufferNotOwned);
+ std::unique_ptr<ScriptCompiler::ConsumeCodeCacheTask> task(
+ ScriptCompiler::StartConsumingCodeCache(
+ isolate(), std::make_unique<ScriptCompiler::CachedData>(
+ cached_data->data, cached_data->length,
+ ScriptCompiler::CachedData::BufferNotOwned)));
+ task->SourceTextAvailable(isolate(), NewString(kPolyglotSource),
+ default_origin.AsScriptOrigin());
+
+ DeserializeThread deserialize_thread(task.release());
+ CHECK(deserialize_thread.Start());
+ deserialize_thread.Join();
+ task = deserialize_thread.TakeTask();
+ CHECK(!task->ShouldMergeWithExistingScript());
+
+ v8::HandleScope handle_scope(isolate());
+ ScriptCompiler::Source source(NewString(kPolyglotSource),
+ default_origin.AsScriptOrigin(),
+ task_cached_data.release(), task.release());
+ Local<Script> script =
+ ScriptCompiler::Compile(context(), &source,
+ ScriptCompiler::kConsumeCodeCache)
+ .ToLocalChecked();
+ CHECK(!script.IsEmpty());
+ CHECK(source.GetCachedData()->rejected);
+
+ Local<Script> run_kept =
+ Script::Compile(context(),
+ NewString("for (const f of globalThis.__keep) f();"))
+ .ToLocalChecked();
+ CHECK(!run_kept->Run(context()).IsEmpty());
+ }
+}
+
} // namespace v8
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page