[inspector][fuzzer] Add inspector fuzzer
This adds a first simple version of the inspector fuzzer, which is a stripped-down version of the inspector-test executable. The fuzzer generates inputs which are compatible with inspector-test. There are still memory leaks, and the fuzzer will probably run into timeouts most of the time. Both of this will be addressed in follow-ups. R=szuend@chromium.org, machenbach@chromium.org Bug: chromium:1142437 Change-Id: I4d13da460f571d791a3642b0705a1f07b442c11b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2505722 Commit-Queue: Clemens Backes <clemensb@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Reviewed-by: Michael Achenbach <machenbach@chromium.org> Cr-Commit-Position: refs/heads/master@{#70922}
This commit is contained in:
parent
e99f0393ad
commit
cf3a842edb
18
BUILD.gn
18
BUILD.gn
@ -4806,6 +4806,7 @@ if (is_fuchsia && !build_with_chromium) {
|
||||
group("v8_fuzzers") {
|
||||
testonly = true
|
||||
data_deps = [
|
||||
":v8_simple_inspector_fuzzer",
|
||||
":v8_simple_json_fuzzer",
|
||||
":v8_simple_multi_return_fuzzer",
|
||||
":v8_simple_parser_fuzzer",
|
||||
@ -5270,6 +5271,23 @@ v8_source_set("wasm_compile_fuzzer") {
|
||||
v8_fuzzer("wasm_compile_fuzzer") {
|
||||
}
|
||||
|
||||
v8_source_set("inspector_fuzzer") {
|
||||
sources = [ "test/fuzzer/inspector-fuzzer.cc" ]
|
||||
|
||||
deps = [
|
||||
":fuzzer_support",
|
||||
"test/inspector:inspector_test",
|
||||
]
|
||||
|
||||
configs = [
|
||||
":external_config",
|
||||
":internal_config_base",
|
||||
]
|
||||
}
|
||||
|
||||
v8_fuzzer("inspector_fuzzer") {
|
||||
}
|
||||
|
||||
# Target to build all generated .cc files.
|
||||
group("v8_generated_cc_files") {
|
||||
testonly = true
|
||||
|
@ -6,13 +6,14 @@ group("v8_fuzzer") {
|
||||
testonly = true
|
||||
|
||||
data_deps = [
|
||||
"../../tools:v8_testrunner",
|
||||
"../..:v8_fuzzers",
|
||||
"../../tools:v8_testrunner",
|
||||
]
|
||||
|
||||
data = [
|
||||
"./fuzzer.status",
|
||||
"./testcfg.py",
|
||||
"./inspector/",
|
||||
"./json/",
|
||||
"./parser/",
|
||||
"./regexp/",
|
||||
|
595
test/fuzzer/inspector-fuzzer.cc
Normal file
595
test/fuzzer/inspector-fuzzer.cc
Normal file
@ -0,0 +1,595 @@
|
||||
// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <unistd.h> // NOLINT
|
||||
#endif // !defined(_WIN32) && !defined(_WIN64)
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/libplatform/libplatform.h"
|
||||
#include "include/v8.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/flags/flags.h"
|
||||
#include "src/heap/read-only-heap.h"
|
||||
#include "src/libplatform/default-platform.h"
|
||||
#include "src/utils/utils.h"
|
||||
#include "src/utils/vector.h"
|
||||
#include "test/inspector/frontend-channel.h"
|
||||
#include "test/inspector/isolate-data.h"
|
||||
#include "test/inspector/task-runner.h"
|
||||
#include "test/inspector/tasks.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
std::vector<TaskRunner*> task_runners;
|
||||
|
||||
void Terminate() {
|
||||
for (TaskRunner* r : task_runners) {
|
||||
r->Terminate();
|
||||
r->Join();
|
||||
}
|
||||
task_runners.clear();
|
||||
}
|
||||
|
||||
class UtilsExtension : public IsolateData::SetupGlobalTask {
|
||||
public:
|
||||
~UtilsExtension() override = default;
|
||||
void Run(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> global) override {
|
||||
v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate);
|
||||
auto Set = [isolate](v8::Local<v8::ObjectTemplate> tmpl, const char* str,
|
||||
v8::Local<v8::Data> value) {
|
||||
tmpl->Set(ToV8String(isolate, str), value,
|
||||
static_cast<v8::PropertyAttribute>(
|
||||
v8::PropertyAttribute::ReadOnly |
|
||||
v8::PropertyAttribute::DontDelete));
|
||||
};
|
||||
Set(utils, "quit",
|
||||
v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit));
|
||||
Set(utils, "compileAndRunWithOrigin",
|
||||
v8::FunctionTemplate::New(isolate,
|
||||
&UtilsExtension::CompileAndRunWithOrigin));
|
||||
Set(utils, "schedulePauseOnNextStatement",
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &UtilsExtension::SchedulePauseOnNextStatement));
|
||||
Set(utils, "cancelPauseOnNextStatement",
|
||||
v8::FunctionTemplate::New(isolate,
|
||||
&UtilsExtension::CancelPauseOnNextStatement));
|
||||
Set(utils, "createContextGroup",
|
||||
v8::FunctionTemplate::New(isolate,
|
||||
&UtilsExtension::CreateContextGroup));
|
||||
Set(utils, "resetContextGroup",
|
||||
v8::FunctionTemplate::New(isolate, &UtilsExtension::ResetContextGroup));
|
||||
Set(utils, "connectSession",
|
||||
v8::FunctionTemplate::New(isolate, &UtilsExtension::ConnectSession));
|
||||
Set(utils, "disconnectSession",
|
||||
v8::FunctionTemplate::New(isolate, &UtilsExtension::DisconnectSession));
|
||||
Set(utils, "sendMessageToBackend",
|
||||
v8::FunctionTemplate::New(isolate,
|
||||
&UtilsExtension::SendMessageToBackend));
|
||||
Set(global, "utils", utils);
|
||||
}
|
||||
|
||||
static void set_backend_task_runner(TaskRunner* runner) {
|
||||
backend_runner_ = runner;
|
||||
}
|
||||
|
||||
static void ClearAllSessions() { channels_.clear(); }
|
||||
|
||||
private:
|
||||
static TaskRunner* backend_runner_;
|
||||
|
||||
static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Terminate();
|
||||
}
|
||||
|
||||
static void CompileAndRunWithOrigin(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 5 || !args[0]->IsInt32() || !args[1]->IsString() ||
|
||||
!args[2]->IsString() || !args[3]->IsInt32() || !args[4]->IsInt32()) {
|
||||
return;
|
||||
}
|
||||
|
||||
backend_runner_->Append(new ExecuteStringTask(
|
||||
args.GetIsolate(), args[0].As<v8::Int32>()->Value(),
|
||||
ToVector(args.GetIsolate(), args[1].As<v8::String>()),
|
||||
args[2].As<v8::String>(), args[3].As<v8::Int32>(),
|
||||
args[4].As<v8::Int32>(), v8::Boolean::New(args.GetIsolate(), false)));
|
||||
}
|
||||
|
||||
static void SchedulePauseOnNextStatement(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
|
||||
!args[2]->IsString()) {
|
||||
return;
|
||||
}
|
||||
std::vector<uint16_t> reason =
|
||||
ToVector(args.GetIsolate(), args[1].As<v8::String>());
|
||||
std::vector<uint16_t> details =
|
||||
ToVector(args.GetIsolate(), args[2].As<v8::String>());
|
||||
int context_group_id = args[0].As<v8::Int32>()->Value();
|
||||
RunSyncTask(backend_runner_,
|
||||
[&context_group_id, &reason, &details](IsolateData* data) {
|
||||
data->SchedulePauseOnNextStatement(
|
||||
context_group_id,
|
||||
v8_inspector::StringView(reason.data(), reason.size()),
|
||||
v8_inspector::StringView(details.data(), details.size()));
|
||||
});
|
||||
}
|
||||
|
||||
static void CancelPauseOnNextStatement(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
||||
return;
|
||||
}
|
||||
int context_group_id = args[0].As<v8::Int32>()->Value();
|
||||
RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
|
||||
data->CancelPauseOnNextStatement(context_group_id);
|
||||
});
|
||||
}
|
||||
|
||||
static void CreateContextGroup(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 0) {
|
||||
return;
|
||||
}
|
||||
int context_group_id = 0;
|
||||
RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
|
||||
context_group_id = data->CreateContextGroup();
|
||||
});
|
||||
args.GetReturnValue().Set(
|
||||
v8::Int32::New(args.GetIsolate(), context_group_id));
|
||||
}
|
||||
|
||||
static void ResetContextGroup(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
||||
return;
|
||||
}
|
||||
int context_group_id = args[0].As<v8::Int32>()->Value();
|
||||
RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
|
||||
data->ResetContextGroup(context_group_id);
|
||||
});
|
||||
}
|
||||
|
||||
static void ConnectSession(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
|
||||
!args[2]->IsFunction()) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
FrontendChannelImpl* channel = new FrontendChannelImpl(
|
||||
IsolateData::FromContext(context)->task_runner(),
|
||||
IsolateData::FromContext(context)->GetContextGroupId(context),
|
||||
args.GetIsolate(), args[2].As<v8::Function>());
|
||||
|
||||
std::vector<uint8_t> state =
|
||||
ToBytes(args.GetIsolate(), args[1].As<v8::String>());
|
||||
int context_group_id = args[0].As<v8::Int32>()->Value();
|
||||
int session_id = 0;
|
||||
RunSyncTask(backend_runner_, [&context_group_id, &session_id, &channel,
|
||||
&state](IsolateData* data) {
|
||||
session_id = data->ConnectSession(
|
||||
context_group_id,
|
||||
v8_inspector::StringView(state.data(), state.size()), channel);
|
||||
channel->set_session_id(session_id);
|
||||
});
|
||||
|
||||
channels_[session_id].reset(channel);
|
||||
args.GetReturnValue().Set(v8::Int32::New(args.GetIsolate(), session_id));
|
||||
}
|
||||
|
||||
static void DisconnectSession(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
||||
return;
|
||||
}
|
||||
int session_id = args[0].As<v8::Int32>()->Value();
|
||||
std::vector<uint8_t> state;
|
||||
RunSyncTask(backend_runner_, [&session_id, &state](IsolateData* data) {
|
||||
state = data->DisconnectSession(session_id);
|
||||
});
|
||||
channels_.erase(session_id);
|
||||
args.GetReturnValue().Set(ToV8String(args.GetIsolate(), state));
|
||||
}
|
||||
|
||||
static void SendMessageToBackend(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {
|
||||
return;
|
||||
}
|
||||
backend_runner_->Append(new SendMessageToBackendTask(
|
||||
args[0].As<v8::Int32>()->Value(),
|
||||
ToVector(args.GetIsolate(), args[1].As<v8::String>())));
|
||||
}
|
||||
|
||||
static std::map<int, std::unique_ptr<FrontendChannelImpl>> channels_;
|
||||
};
|
||||
|
||||
TaskRunner* UtilsExtension::backend_runner_ = nullptr;
|
||||
std::map<int, std::unique_ptr<FrontendChannelImpl>> UtilsExtension::channels_;
|
||||
|
||||
bool StrictAccessCheck(v8::Local<v8::Context> accessing_context,
|
||||
v8::Local<v8::Object> accessed_object,
|
||||
v8::Local<v8::Value> data) {
|
||||
CHECK(accessing_context.IsEmpty());
|
||||
return accessing_context.IsEmpty();
|
||||
}
|
||||
|
||||
class InspectorExtension : public IsolateData::SetupGlobalTask {
|
||||
public:
|
||||
~InspectorExtension() override = default;
|
||||
void Run(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> global) override {
|
||||
v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate);
|
||||
inspector->Set(ToV8String(isolate, "fireContextCreated"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::FireContextCreated));
|
||||
inspector->Set(ToV8String(isolate, "fireContextDestroyed"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::FireContextDestroyed));
|
||||
inspector->Set(
|
||||
ToV8String(isolate, "freeContext"),
|
||||
v8::FunctionTemplate::New(isolate, &InspectorExtension::FreeContext));
|
||||
inspector->Set(ToV8String(isolate, "addInspectedObject"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::AddInspectedObject));
|
||||
inspector->Set(ToV8String(isolate, "setMaxAsyncTaskStacks"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::SetMaxAsyncTaskStacks));
|
||||
inspector->Set(
|
||||
ToV8String(isolate, "dumpAsyncTaskStacksStateForTest"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest));
|
||||
inspector->Set(
|
||||
ToV8String(isolate, "breakProgram"),
|
||||
v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram));
|
||||
inspector->Set(
|
||||
ToV8String(isolate, "createObjectWithStrictCheck"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::CreateObjectWithStrictCheck));
|
||||
inspector->Set(ToV8String(isolate, "callWithScheduledBreak"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::CallWithScheduledBreak));
|
||||
inspector->Set(ToV8String(isolate, "allowAccessorFormatting"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::AllowAccessorFormatting));
|
||||
inspector->Set(
|
||||
ToV8String(isolate, "markObjectAsNotInspectable"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::MarkObjectAsNotInspectable));
|
||||
inspector->Set(ToV8String(isolate, "createObjectWithAccessor"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::CreateObjectWithAccessor));
|
||||
inspector->Set(ToV8String(isolate, "storeCurrentStackTrace"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::StoreCurrentStackTrace));
|
||||
inspector->Set(ToV8String(isolate, "externalAsyncTaskStarted"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::ExternalAsyncTaskStarted));
|
||||
inspector->Set(
|
||||
ToV8String(isolate, "externalAsyncTaskFinished"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::ExternalAsyncTaskFinished));
|
||||
inspector->Set(ToV8String(isolate, "scheduleWithAsyncStack"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::ScheduleWithAsyncStack));
|
||||
inspector->Set(
|
||||
ToV8String(isolate, "setAllowCodeGenerationFromStrings"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::SetAllowCodeGenerationFromStrings));
|
||||
inspector->Set(ToV8String(isolate, "setResourceNamePrefix"),
|
||||
v8::FunctionTemplate::New(
|
||||
isolate, &InspectorExtension::SetResourceNamePrefix));
|
||||
global->Set(ToV8String(isolate, "inspector"), inspector);
|
||||
}
|
||||
|
||||
private:
|
||||
static void FireContextCreated(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
data->FireContextCreated(context, data->GetContextGroupId(context),
|
||||
v8_inspector::StringView());
|
||||
}
|
||||
|
||||
static void FireContextDestroyed(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
data->FireContextDestroyed(context);
|
||||
}
|
||||
|
||||
static void FreeContext(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
data->FreeContext(context);
|
||||
}
|
||||
|
||||
static void AddInspectedObject(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 2 || !args[0]->IsInt32()) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
data->AddInspectedObject(args[0].As<v8::Int32>()->Value(), args[1]);
|
||||
}
|
||||
|
||||
static void SetMaxAsyncTaskStacks(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
||||
return;
|
||||
}
|
||||
IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
|
||||
->SetMaxAsyncTaskStacksForTest(args[0].As<v8::Int32>()->Value());
|
||||
}
|
||||
|
||||
static void DumpAsyncTaskStacksStateForTest(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 0) {
|
||||
return;
|
||||
}
|
||||
IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
|
||||
->DumpAsyncTaskStacksStateForTest();
|
||||
}
|
||||
|
||||
static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
std::vector<uint16_t> reason =
|
||||
ToVector(args.GetIsolate(), args[0].As<v8::String>());
|
||||
v8_inspector::StringView reason_view(reason.data(), reason.size());
|
||||
std::vector<uint16_t> details =
|
||||
ToVector(args.GetIsolate(), args[1].As<v8::String>());
|
||||
v8_inspector::StringView details_view(details.data(), details.size());
|
||||
data->BreakProgram(data->GetContextGroupId(context), reason_view,
|
||||
details_view);
|
||||
}
|
||||
|
||||
static void CreateObjectWithStrictCheck(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 0) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::ObjectTemplate> templ =
|
||||
v8::ObjectTemplate::New(args.GetIsolate());
|
||||
templ->SetAccessCheckCallback(&StrictAccessCheck);
|
||||
args.GetReturnValue().Set(
|
||||
templ->NewInstance(args.GetIsolate()->GetCurrentContext())
|
||||
.ToLocalChecked());
|
||||
}
|
||||
|
||||
static void CallWithScheduledBreak(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
|
||||
!args[2]->IsString()) {
|
||||
return;
|
||||
}
|
||||
std::vector<uint16_t> reason =
|
||||
ToVector(args.GetIsolate(), args[1].As<v8::String>());
|
||||
v8_inspector::StringView reason_view(reason.data(), reason.size());
|
||||
std::vector<uint16_t> details =
|
||||
ToVector(args.GetIsolate(), args[2].As<v8::String>());
|
||||
v8_inspector::StringView details_view(details.data(), details.size());
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
int context_group_id = data->GetContextGroupId(context);
|
||||
data->SchedulePauseOnNextStatement(context_group_id, reason_view,
|
||||
details_view);
|
||||
v8::MaybeLocal<v8::Value> result;
|
||||
result = args[0].As<v8::Function>()->Call(context, context->Global(), 0,
|
||||
nullptr);
|
||||
data->CancelPauseOnNextStatement(context_group_id);
|
||||
}
|
||||
|
||||
static void AllowAccessorFormatting(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsObject()) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Object> object = args[0].As<v8::Object>();
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi(
|
||||
isolate, ToV8String(isolate, "allowAccessorFormatting"));
|
||||
object
|
||||
->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate,
|
||||
v8::Null(isolate))
|
||||
.ToChecked();
|
||||
}
|
||||
|
||||
static void MarkObjectAsNotInspectable(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsObject()) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Object> object = args[0].As<v8::Object>();
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::Local<v8::Private> notInspectablePrivate =
|
||||
v8::Private::ForApi(isolate, ToV8String(isolate, "notInspectable"));
|
||||
object
|
||||
->SetPrivate(isolate->GetCurrentContext(), notInspectablePrivate,
|
||||
v8::True(isolate))
|
||||
.ToChecked();
|
||||
}
|
||||
|
||||
static void CreateObjectWithAccessor(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsBoolean()) {
|
||||
return;
|
||||
}
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
|
||||
if (args[1].As<v8::Boolean>()->Value()) {
|
||||
templ->SetAccessor(v8::Local<v8::String>::Cast(args[0]), AccessorGetter,
|
||||
AccessorSetter);
|
||||
} else {
|
||||
templ->SetAccessor(v8::Local<v8::String>::Cast(args[0]), AccessorGetter);
|
||||
}
|
||||
args.GetReturnValue().Set(
|
||||
templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked());
|
||||
}
|
||||
|
||||
static void AccessorGetter(v8::Local<v8::String> property,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
v8::Isolate* isolate = info.GetIsolate();
|
||||
isolate->ThrowException(ToV8String(isolate, "Getter is called"));
|
||||
}
|
||||
|
||||
static void AccessorSetter(v8::Local<v8::String> property,
|
||||
v8::Local<v8::Value> value,
|
||||
const v8::PropertyCallbackInfo<void>& info) {
|
||||
v8::Isolate* isolate = info.GetIsolate();
|
||||
isolate->ThrowException(ToV8String(isolate, "Setter is called"));
|
||||
}
|
||||
|
||||
static void StoreCurrentStackTrace(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsString()) {
|
||||
return;
|
||||
}
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
std::vector<uint16_t> description =
|
||||
ToVector(isolate, args[0].As<v8::String>());
|
||||
v8_inspector::StringView description_view(description.data(),
|
||||
description.size());
|
||||
v8_inspector::V8StackTraceId id =
|
||||
data->StoreCurrentStackTrace(description_view);
|
||||
v8::Local<v8::ArrayBuffer> buffer =
|
||||
v8::ArrayBuffer::New(isolate, sizeof(id));
|
||||
*static_cast<v8_inspector::V8StackTraceId*>(
|
||||
buffer->GetBackingStore()->Data()) = id;
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
|
||||
static void ExternalAsyncTaskStarted(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
v8_inspector::V8StackTraceId* id =
|
||||
static_cast<v8_inspector::V8StackTraceId*>(
|
||||
args[0].As<v8::ArrayBuffer>()->GetBackingStore()->Data());
|
||||
data->ExternalAsyncTaskStarted(*id);
|
||||
}
|
||||
|
||||
static void ExternalAsyncTaskFinished(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
|
||||
return;
|
||||
}
|
||||
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
v8_inspector::V8StackTraceId* id =
|
||||
static_cast<v8_inspector::V8StackTraceId*>(
|
||||
args[0].As<v8::ArrayBuffer>()->GetBackingStore()->Data());
|
||||
data->ExternalAsyncTaskFinished(*id);
|
||||
}
|
||||
|
||||
static void ScheduleWithAsyncStack(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
|
||||
!args[2]->IsBoolean()) {
|
||||
return;
|
||||
}
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
int context_group_id = data->GetContextGroupId(context);
|
||||
bool with_empty_stack = args[2].As<v8::Boolean>()->Value();
|
||||
if (with_empty_stack) context->Exit();
|
||||
|
||||
std::vector<uint16_t> task_name =
|
||||
ToVector(isolate, args[1].As<v8::String>());
|
||||
v8_inspector::StringView task_name_view(task_name.data(), task_name.size());
|
||||
|
||||
RunAsyncTask(data->task_runner(), task_name_view,
|
||||
new SetTimeoutTask(context_group_id, isolate,
|
||||
v8::Local<v8::Function>::Cast(args[0])));
|
||||
if (with_empty_stack) context->Enter();
|
||||
}
|
||||
|
||||
static void SetAllowCodeGenerationFromStrings(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsBoolean()) {
|
||||
return;
|
||||
}
|
||||
args.GetIsolate()->GetCurrentContext()->AllowCodeGenerationFromStrings(
|
||||
args[0].As<v8::Boolean>()->Value());
|
||||
}
|
||||
|
||||
static void SetResourceNamePrefix(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
if (args.Length() != 1 || !args[0]->IsString()) {
|
||||
return;
|
||||
}
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
IsolateData* data = IsolateData::FromContext(context);
|
||||
data->SetResourceNamePrefix(v8::Local<v8::String>::Cast(args[0]));
|
||||
}
|
||||
};
|
||||
|
||||
using CharVector = v8::internal::Vector<const char>;
|
||||
|
||||
void FuzzInspector(const uint8_t* data, size_t size) {
|
||||
base::Semaphore ready_semaphore(0);
|
||||
|
||||
IsolateData::SetupGlobalTasks frontend_extensions;
|
||||
frontend_extensions.emplace_back(new UtilsExtension());
|
||||
TaskRunner frontend_runner(std::move(frontend_extensions), true,
|
||||
&ready_semaphore, nullptr, false);
|
||||
ready_semaphore.Wait();
|
||||
|
||||
int frontend_context_group_id = 0;
|
||||
RunSyncTask(&frontend_runner,
|
||||
[&frontend_context_group_id](IsolateData* data) {
|
||||
frontend_context_group_id = data->CreateContextGroup();
|
||||
});
|
||||
|
||||
IsolateData::SetupGlobalTasks backend_extensions;
|
||||
backend_extensions.emplace_back(new SetTimeoutExtension());
|
||||
backend_extensions.emplace_back(new InspectorExtension());
|
||||
TaskRunner backend_runner(std::move(backend_extensions), false,
|
||||
&ready_semaphore, nullptr, true);
|
||||
ready_semaphore.Wait();
|
||||
UtilsExtension::set_backend_task_runner(&backend_runner);
|
||||
|
||||
task_runners.push_back(&frontend_runner);
|
||||
task_runners.push_back(&backend_runner);
|
||||
|
||||
frontend_runner.Append(new ExecuteStringTask(
|
||||
std::string{reinterpret_cast<const char*>(data), size},
|
||||
frontend_context_group_id));
|
||||
|
||||
frontend_runner.Join();
|
||||
backend_runner.Join();
|
||||
|
||||
UtilsExtension::ClearAllSessions();
|
||||
|
||||
// TaskRunners go out of scope here, which causes Isolate teardown and all
|
||||
// running background tasks to be properly joined.
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
v8::internal::FuzzInspector(data, size);
|
||||
return 0;
|
||||
}
|
1
test/fuzzer/inspector/foo
Normal file
1
test/fuzzer/inspector/foo
Normal file
@ -0,0 +1 @@
|
||||
smoke test
|
@ -8,10 +8,11 @@ from testrunner.local import testsuite
|
||||
from testrunner.objects import testcase
|
||||
|
||||
SUB_TESTS = [
|
||||
'inspector',
|
||||
'json',
|
||||
'parser',
|
||||
'regexp_builtins',
|
||||
'regexp',
|
||||
'regexp_builtins',
|
||||
'multi_return',
|
||||
'wasm',
|
||||
'wasm_async',
|
||||
|
@ -4,12 +4,9 @@
|
||||
|
||||
import("../../gni/v8.gni")
|
||||
|
||||
v8_executable("inspector-test") {
|
||||
testonly = true
|
||||
|
||||
v8_source_set("inspector_test") {
|
||||
sources = [
|
||||
"frontend-channel.h",
|
||||
"inspector-test.cc",
|
||||
"isolate-data.cc",
|
||||
"isolate-data.h",
|
||||
"task-runner.cc",
|
||||
@ -20,16 +17,28 @@ v8_executable("inspector-test") {
|
||||
"utils.h",
|
||||
]
|
||||
|
||||
configs = [ "../..:internal_config_base" ]
|
||||
|
||||
public_deps = [
|
||||
"../..:v8",
|
||||
"../..:v8_libbase",
|
||||
"../..:v8_libplatform",
|
||||
"../../src/inspector:inspector_test_headers",
|
||||
]
|
||||
}
|
||||
|
||||
v8_executable("inspector-test") {
|
||||
testonly = true
|
||||
|
||||
sources = [ "inspector-test.cc" ]
|
||||
|
||||
configs = [
|
||||
"../..:external_config",
|
||||
"../..:internal_config_base",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../..:v8",
|
||||
"../..:v8_libbase",
|
||||
"../..:v8_libplatform",
|
||||
"../../src/inspector:inspector_test_headers",
|
||||
":inspector_test",
|
||||
"//build/win:default_exe_manifest",
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user