-
Notifications
You must be signed in to change notification settings - Fork 126
Open
Description
Thanks for building and maintaining quickjs-emscripten. I'm interested in using it to safely run user-defined logic on my server. I've come across a case where one user can make the vm take a very long time to run out of memory, and yet the interrupt callback never runs:
import { getQuickJS, Scope } from "quickjs-emscripten"
const qjs = await getQuickJS()
const scope = new Scope()
const runtime = scope.manage(qjs.newRuntime())
const vm = scope.manage(
runtime.newContext()
)
runtime.setInterruptHandler(() => true) // Always interrupt
runtime.setMemoryLimit(1024 * 640)
runtime.setMaxStackSize(1024 * 320)
// "Warm up" the vm - this DOES get interrupted, but only during the first run
try {
vm.unwrapResult(vm.evalCode("{}")).dispose()
} catch {}
// Do something slow
try {
// Make a large array and convert it to a string
// The array is huge so this could take 10-30s
vm.unwrapResult(vm.evalCode("new Array(1_000_000_000) + ''\nundefined")).consume(vm.dump) // <--
} catch(e) {
// Eventually I get InternalError: out of memory, but not soon enough!
console.error(`${e}`)
}
scope.dispose()This is a big issue because one user can affect the availability of the server for other users. I'd like to get the interrupt callback to run during my evalCode call, and would happily sacrifice performance to do so. Is this possible?
I've seen multiple places state that the interrupt handler runs every 1000 or so "instructions" or "cycles", is this 20s long operation really a single cycle?
Metadata
Metadata
Assignees
Labels
No labels