Hello V8-Experts,
I am working on a project where I need to run untrusted user provided
javascript. I am worried about faulty user script bringing down the entire
application by hogging memory. So, idea is to implement budgeting of heap
memory for each javascript.
I looked at different projects that tried to solve the process exit due to
OOM error. Few ideas that collected are
1. Running separate thread and RequestInterrupt. In interrupt
routine, using GetHeapStatistics to check heap usage.
https://github.com/phpv8/v8js/blob/php7/v8js_timer.cc#L36:13
2. Using AddGCEpilogueCallback and GetHeapStatistics
https://github.com/discourse/mini_racer/blob/master/ext/mini_racer_extension/mini_racer_extension.cc#L194:13
I am worried about the overhead and performance impact of these approaches.
Recently, following commit introduced "AddNearHeapLimitCallback".
Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=824214
Commit:
https://chromium.googlesource.com/v8/v8/+/84a80e103b090f35334fe2d168ece17489395417
I tried using this API in my sample program to detect OOM and dispose the
isolate executing faulty script. [Please see below for the sample program]
My experiment *detected* the OOM error and terminated the faulty script.
I have few questions regarding this API:
1. Are there any caveats in using this API? How reliably it detects the OOM
condition? Are there scenarios in which it will fail to detect the OOM?
2. In the sample code below, in function, "MyNearHeapLimitCallback": I am
terminating the execution and returning the new heap limit by adding 5MB.
If I return the initial_heap_limit as is (i.e. without adding 5 MB), the
faulty script will make my application crash with OOM. Why?
3. When the AddNearHeapLimitCallback is being called, I assume that the
javascript execution is paused. Is this a correct understanding?
Thanks, Prakash
==== Sample program ==
size_t MyNearHeapLimitCallback(void* data, size_t current_heap_limit,
size_t initial_heap_limit) {
v8::Isolate *isolate = (v8::Isolate *)data;
isolate->TerminateExecution();
return initial_heap_limit + 5 * 1024 * 1024;
}
int main(int argc, char* argv[]) {
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();
while(true) {
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::ResourceConstraints constraints;
constraints.set_max_old_space_size(10);
create_params.constraints = constraints;
v8::Isolate* isolate = v8::Isolate::New(create_params);
isolate->AddNearHeapLimitCallback(MyNearHeapLimitCallback, isolate);
{
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
v8::Local<v8::String> source =
v8::String::NewFromUtf8(isolate, "a = []; for (;;) {
a.push('hello'); }",
v8::NewStringType::kNormal)
.ToLocalChecked();
v8::Local<v8::Script> script = v8::Script::Compile(context,
source).ToLocalChecked();
v8::TryCatch try_catch(isolate);
v8::MaybeLocal<v8::Value> result;
result = script->Run(context);
if (try_catch.HasCaught() && try_catch.HasTerminated()) {
isolate->CancelTerminateExecution();
}
}
delete create_params.array_buffer_allocator;
isolate->Dispose();
}
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
return 0;
}
--
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.