Remix.run Logo
▲ EGreg a day ago

Good question! Nothing in SafeScript itself prevents it. Instrumenting the code to prevent this would be too costly. A script can do

  var a = [];
  for (var i = 0; i < 10000000; i++)
   { a.push({x: i}); }
But that’s because it’s up to the host to sandbox the script, eg in WebWorkers or Node VM Isolates, using Q.Sandbox and use Q.Proxy to transparently pass in the Facades.

In PHP the situation is excellent. That’s language has support for checking how much memory was used, so our injected checks already works there:

  if ($d > 0 && ($o === null || ($o % 1000) === 0)) {
    if (microtime(true) >= $d) {
        throw new \RuntimeException('SafeScript: timeout exceeded');
    }
    $ml = $GLOBALS['__safescript_memory_limit'] ?? 0;
    if ($ml > 0 && memory_get_usage() > $ml) {
        throw new \RuntimeException('SafeScript: memory limit exceeded (' . $ml . ' bytes)');
    }
  }
https://github.com/SafeScript/safescript-php

For native embedded applications, where SafeScript is positioned to replace Lua, the situation is quite good. QuickJS already has JS_SetMemoryLimit() - a hard byte ceiling, which throws when hit. In fact the https://github.com/SafeScript/safescript-quickjs repo already uses this.

You can think of this as the “belt-and-suspenders” approach. Perhaps a future version of SafeScript would instrument the actual imperative code to catch these, same as it catches a script that tries to peg the CPU. But so far, I haven’t found a good way, without totally overriding most Javascript primitives, objects and operations. Any suggestions?

▲hyperhello a day ago | parent [-]

Does the system do its own allocations with a memory block or does it basically depend on the host to malloc?

▲EGreg a day ago | parent [-]

The system is basically JS, you can run it however you like!

SafeScript actually compiles to plain JavaScript, just like Typescript does

In PHP, it compiles to plain PHP :)