Commit 98d5e413 authored by Hitoshi Yoshida's avatar Hitoshi Yoshida Committed by Commit Bot

bindings: Disable V8ContextSnapshot if deserialization fail

While deserializing V8 contexts from snapshot, the process can
fail, unfortunately.
This CL makes the routine to catch such unexpected cases and
disables the feature to avoid crashes.


Bug: 881417
Change-Id: I874a16b63fd6b8ae7a3532bc5c662531a895e3ed
Reviewed-on: https://chromium-review.googlesource.com/c/1258786
Commit-Queue: Hitoshi Yoshida <peria@chromium.org>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596974}
parent 76bf417b
...@@ -114,9 +114,12 @@ const WrapperTypeInfo* FieldTypeToWrapperTypeInfo(InternalFieldType type) { ...@@ -114,9 +114,12 @@ const WrapperTypeInfo* FieldTypeToWrapperTypeInfo(InternalFieldType type) {
struct DataForDeserializer { struct DataForDeserializer {
STACK_ALLOCATED(); STACK_ALLOCATED();
public: public:
DataForDeserializer(Document* document) : document(document) {}
Member<Document> document; Member<Document> document;
// Figures if we failed the deserialization.
bool did_fail = false;
}; };
} // namespace } // namespace
...@@ -132,13 +135,22 @@ v8::Local<v8::Context> V8ContextSnapshot::CreateContextFromSnapshot( ...@@ -132,13 +135,22 @@ v8::Local<v8::Context> V8ContextSnapshot::CreateContextFromSnapshot(
} }
const int index = GetSnapshotIndexForWorld(world); const int index = GetSnapshotIndexForWorld(world);
DataForDeserializer data{document}; DataForDeserializer data(document);
v8::DeserializeInternalFieldsCallback callback = v8::DeserializeInternalFieldsCallback callback =
v8::DeserializeInternalFieldsCallback(&DeserializeInternalField, &data); v8::DeserializeInternalFieldsCallback(&DeserializeInternalField, &data);
v8::Local<v8::Context> context = v8::Local<v8::Context> context =
v8::Context::FromSnapshot(isolate, index, callback, v8::Context::FromSnapshot(isolate, index, callback,
extension_configuration, global_proxy) extension_configuration, global_proxy)
.ToLocalChecked(); .ToLocalChecked();
// In case we fail to deserialize v8::Context from snapshot,
// disable the snapshot feature and returns an empty handle.
// TODO(peria): Drop this fallback routine. crbug.com/881417
if (data.did_fail) {
V8PerIsolateData::From(isolate)->BailoutAndDisableV8ContextSnapshot();
return v8::Local<v8::Context>();
}
VLOG(1) << "A context is created from snapshot for " VLOG(1) << "A context is created from snapshot for "
<< (world.IsMainWorld() ? "" : "non-") << "main world"; << (world.IsMainWorld() ? "" : "non-") << "main world";
...@@ -351,27 +363,45 @@ void V8ContextSnapshot::DeserializeInternalField(v8::Local<v8::Object> object, ...@@ -351,27 +363,45 @@ void V8ContextSnapshot::DeserializeInternalField(v8::Local<v8::Object> object,
*reinterpret_cast<const InternalFieldType*>(payload.data); *reinterpret_cast<const InternalFieldType*>(payload.data);
const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type); const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type);
DataForDeserializer* embed_data = static_cast<DataForDeserializer*>(ptr);
switch (type) { switch (type) {
case InternalFieldType::kNodeType: case InternalFieldType::kNodeType:
case InternalFieldType::kDocumentType: case InternalFieldType::kDocumentType:
case InternalFieldType::kHTMLDocumentType: { case InternalFieldType::kHTMLDocumentType: {
CHECK_EQ(index, kV8DOMWrapperTypeIndex); // TODO(peria): Make this branch back to CHECK_EQ. crbug.com/881417
if (index != kV8DOMWrapperTypeIndex) {
LOG(ERROR) << "Invalid index for wrpper type info: " << index;
embed_data->did_fail = true;
return;
}
object->SetAlignedPointerInInternalField( object->SetAlignedPointerInInternalField(
index, const_cast<WrapperTypeInfo*>(wrapper_type_info)); index, const_cast<WrapperTypeInfo*>(wrapper_type_info));
return; return;
} }
case InternalFieldType::kHTMLDocumentObject: { case InternalFieldType::kHTMLDocumentObject: {
// There seems to be few crash reports with invalid |index|.
// In such cases, we fallback to create v8::Context without snapshots.
// TODO(peria): Make this branch back to CHECK_EQ. crbug.com/881417
if (index != kV8DOMWrapperObjectIndex) {
LOG(ERROR) << "Invalid index for HTMLDocument object: " << index;
embed_data->did_fail = true;
return;
}
// The below code handles window.document on the main world. // The below code handles window.document on the main world.
CHECK_EQ(index, kV8DOMWrapperObjectIndex);
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
DataForDeserializer* data = static_cast<DataForDeserializer*>(ptr); ScriptWrappable* document = embed_data->document;
ScriptWrappable* document = data->document;
DCHECK(document); DCHECK(document);
// Make reference from wrapper to document // Make reference from wrapper to document
object->SetAlignedPointerInInternalField(index, document); object->SetAlignedPointerInInternalField(index, document);
// Make reference from document to wrapper // Make reference from document to wrapper
CHECK(document->SetWrapper(isolate, wrapper_type_info, object)); // TODO(peria): Make this branch back to CHECK. crbug.com/881417
if (!document->SetWrapper(isolate, wrapper_type_info, object)) {
LOG(ERROR) << "Failed to set HTMLDocument wrapper on Blink object.";
embed_data->did_fail = true;
return;
}
WrapperTypeInfo::WrapperCreated(); WrapperTypeInfo::WrapperCreated();
return; return;
} }
......
...@@ -157,6 +157,10 @@ class PLATFORM_EXPORT V8PerIsolateData { ...@@ -157,6 +157,10 @@ class PLATFORM_EXPORT V8PerIsolateData {
V8ContextSnapshotMode GetV8ContextSnapshotMode() const { V8ContextSnapshotMode GetV8ContextSnapshotMode() const {
return v8_context_snapshot_mode_; return v8_context_snapshot_mode_;
} }
void BailoutAndDisableV8ContextSnapshot() {
DCHECK_EQ(V8ContextSnapshotMode::kUseSnapshot, v8_context_snapshot_mode_);
v8_context_snapshot_mode_ = V8ContextSnapshotMode::kDontUseSnapshot;
}
// Accessor to the cache of cross-origin accessible operation's templates. // Accessor to the cache of cross-origin accessible operation's templates.
// Created templates get automatically cached. // Created templates get automatically cached.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment