Skip to content

Instantly share code, notes, and snippets.

@msrkp

msrkp/ciso.cc Secret

Created November 3, 2024 10:50
Show Gist options
  • Select an option

  • Save msrkp/1ed54c513caef9f0e0b5cfa9b9c35cde to your computer and use it in GitHub Desktop.

Select an option

Save msrkp/1ed54c513caef9f0e0b5cfa9b9c35cde to your computer and use it in GitHub Desktop.
//`$ clang++ hello_world.cc -I. -Iinclude -Lout.gn/discord.release/obj -lv8_monolith -o hello_world -std=c++17 -stdlib=libc++ -DV8_COMPRESS_POINTERS -target arm64-apple-macos11 -lpthread&& ./hello_world`
#include <libplatform/libplatform.h>
#include <v8.h>
#include <iostream>
namespace my_bridge {
const int kMaxRecursion = 1000;
bool DeepFreeze(const v8::Local<v8::Object>& object,
v8::Local<v8::Context> context) {
v8::Local<v8::Array> property_names =
object->GetOwnPropertyNames(context).ToLocalChecked();
for (uint32_t i = 0; i < property_names->Length(); ++i) {
v8::Local<v8::Value> child =
object->Get(context, property_names->Get(context, i).ToLocalChecked())
.ToLocalChecked();
if (child->IsObject()) {
DeepFreeze(child.As<v8::Object>(), context);
}
}
return object->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen)
.ToChecked();
}
v8::MaybeLocal<v8::Value> PassValueToOtherContext(
v8::Local<v8::Context> source_context,
v8::Local<v8::Context> destination_context, v8::Local<v8::Value> value) {
v8::Context::Scope destination_scope(destination_context);
if (value->IsFunction()) {
v8::Local<v8::Function> original_func = value.As<v8::Function>();
return v8::MaybeLocal<v8::Value>(
v8::Function::New(destination_context,
[](const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(
v8::String::NewFromUtf8(info.GetIsolate(),
"Proxy function called")
.ToLocalChecked());
})
.ToLocalChecked());
}
if (value->IsObject()) {
v8::Local<v8::Object> obj = value.As<v8::Object>();
DeepFreeze(obj, destination_context);
return obj;
}
return v8::MaybeLocal<v8::Value>(value);
}
void ExposeInMainWorld(v8::Isolate* isolate,
v8::Local<v8::Context> main_context,
v8::Local<v8::Object> object, const std::string& name) {
v8::Context::Scope main_scope(main_context);
main_context->Global()
->Set(main_context,
v8::String::NewFromUtf8(isolate, name.c_str()).ToLocalChecked(),
object)
.Check();
}
} // namespace my_bridge
void ConsoleLog(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() < 1) return;
v8::String::Utf8Value str(args.GetIsolate(), args[0]);
std::cout << *str << std::endl;
}
void SetUpConsole(v8::Isolate* isolate, v8::Local<v8::Context> context) {
v8::Context::Scope context_scope(context);
v8::Local<v8::Object> console = v8::Object::New(isolate);
console
->Set(context, v8::String::NewFromUtf8(isolate, "log").ToLocalChecked(),
v8::Function::New(context, ConsoleLog).ToLocalChecked())
.Check();
context->Global()
->Set(context,
v8::String::NewFromUtf8(isolate, "console").ToLocalChecked(),
console)
.Check();
}
void InitializeContextBridge(v8::Isolate* isolate) {
v8::HandleScope handle_scope(isolate);
auto main_context = v8::Context::New(isolate); // [1]
SetUpConsole(isolate, main_context);
v8::Global<v8::Context> main_context_global(isolate, main_context);
isolate->SetData(0, &main_context_global);
auto isolated_context = v8::Context::New(isolate); // [2]
SetUpConsole(isolate, isolated_context);
v8::Context::Scope isolated_scope(isolated_context);
isolated_context->Global()
->Set(isolated_context,
v8::String::NewFromUtf8(isolate, "ExposeInMainWorld")
.ToLocalChecked(),
v8::Function::New(
isolated_context,
[](const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() < 2 || !args[0]->IsString() ||
!args[1]->IsObject()) {
args.GetIsolate()->ThrowException(
v8::String::NewFromUtf8(args.GetIsolate(),
"Invalid arguments")
.ToLocalChecked());
return;
}
v8::Isolate* isolate = args.GetIsolate();
v8::String::Utf8Value name(isolate, args[0]);
v8::Local<v8::Object> object = args[1].As<v8::Object>();
v8::Local<v8::Context> main_context =
v8::Local<v8::Context>::New(
isolate, *static_cast<v8::Global<v8::Context>*>(
isolate->GetData(0)));
my_bridge::ExposeInMainWorld(isolate, main_context, object,
*name);
})
.ToLocalChecked())
.Check();
const char* isolated_code = R"(
console.log("In Isolated Context:");
var regexp = /^only_allow_this_[a-z0-9_-]+$/;
%DebugPrint(regexp);
%DebugPrint(regexp.source);
function requireModule(name) {
if (regexp.test(name) ) {
return false;
}
return true;
}
const myObject = { name: "isolated_object", requireModule:requireModule}
ExposeInMainWorld("exposedObject", myObject);
%DebugPrint(myObject);
)";
v8::Local<v8::String> source =
v8::String::NewFromUtf8(isolate, isolated_code).ToLocalChecked();
v8::Local<v8::Script> script;
if (!v8::Script::Compile(isolated_context, source).ToLocal(&script)) {
std::cerr << "Failed to compile isolated context script." << std::endl;
return;
}
script->Run(isolated_context).ToLocalChecked();
const char* main_code = R"(
console.log("In Main Context:");
%DebugPrint(exposedObject);
console.log(exposedObject.requireModule('test'));
)";
v8::Local<v8::String> main_source =
v8::String::NewFromUtf8(isolate, main_code).ToLocalChecked();
v8::Local<v8::Script> main_script;
if (!v8::Script::Compile(main_context, main_source).ToLocal(&main_script)) {
std::cerr << "Failed to compile main context script." << std::endl;
return;
}
main_script->Run(main_context).ToLocalChecked();
}
int main(int argc, char* argv[]) {
// Set V8 flags to increase memory limits and allow native syntax
const char* flags =
"--max-old-space-size=2048 --max-semi-space-size=64 "
"--allow-natives-syntax";
v8::V8::SetFlagsFromString(flags);
v8::V8::SetFlagsFromString(flags);
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);
InitializeContextBridge(isolate);
}
isolate->Dispose();
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
delete create_params.array_buffer_allocator;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment