NodeJS has a package called a VM that is used to create a virtual machine that runs NodeJS code (JavaScript, ECMAScript).
var vm = require(‘vm‘);
There are not many methods for this VM:
- Vm. Script
- Vm.createscript
- Vm.createcontext
- Vm.runindebugcontext
- Vm.runincontext
- Vm.runinnewcontext
- Vm.runinthiscontext
- Vm.iscontext
View Nodejs Documentation: VMS
Briefly
In a nutshell, this package has two objects, script, context, and so on.
The context contains various objects that are currently operational, and can therefore be referred to as a running environment. If we create a new context and isolate it from the current context, then it is equivalent to creating a sandbox where the Nodejs script running in the sandbox will not affect the external environment.
In the object of script, the sense of existence is not very strong, because it is constructed directly from a string, and in many cases it can be replaced directly with a code string.
Run the Nodejs code in the sandbox
var=require(‘vm‘);var= vm.// Empty Contextvar=‘var x = 1;‘vm.runInContext(code, sandbox);console.log// {x: 1}
Nodejs Evaluation Machine
A class of evaluation machines can be designed for Nodejs, which can directly check the variables in the sandbox to determine whether the program is correct.
At this point, the initial context is equivalent to the input data.
varVM =require(' VMS ');varTestcases = []; for(vari =0; I < +; i++) {varA = Math.random () * +;varb = Math.random () * +; Testcases.push ({input: {aAb: b},Output: {ans: A + B,}})}varCode =' ans = a + B + (a < 5? 1:0) '; Testcases.foreach(e, i) = = { var sandbox = Vm.createcontext (e.input); Vm.runincontext (code, sandbox, {time: +}); // time limit: $ ms for (var key in e.output) { if(E.OUTPU T[key]! = Sandbox[key]) { console. log ('testing failed in case ${i}') ; break; } } })
The above program generates 1000 sets of random numbers, builds the sandbox one after the other, runs the code in it, and finally checks to see if certain variables in the running environment meet the requirements.
Here is a very simple A + B problem, but here the code adds a disturbance, when the a < 5 answer is wrong, this is deliberately made error, used to demonstrate the situation of the error occurred.
As you can see, the code to be tested does not depend on I/O, and the user of the evaluation system does not have to include the operation StdIn, stdout code when submitting the code. It's like writing a function.
Heavy Duty Require
Although when you do not do anything, when the user code contains the var x = require(XXX); attempt to load the package, the error will be reported ReferenceError: require is not defined .
Because there is no such require function in their sandbox, there is no way to load the package, not to load some dangerous packages, as vm with fs .
However, if you must open the package to them for reference, you can throw the external require function into the sandbox:
var sandbox = vm.createContext({ requirerequire})
In this way the user code contains the Require function will not error, will be executed correctly.
For safety, you decide to filter out some dangerous packages:
var myRequire(package){ if(package‘fs‘package‘vm‘return {}; returnrequire(package);}var sandbox = vm.createContext({ require: myRequire});
This allows users to refer to the FS, VMS, these packages will find that the resulting is an empty object, and naturally can not invoke the method.
The logic of filtering is very free, you can add hooks inside, even reload the entire require function, and even add some of your own packages.
Nodejs virtual Machines