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.

Reply via email to