Combine NodeJS Fibers + VM Sandbox
Я хочу запустить ненадежный код в Node, который может выглядеть следующим образом:
for (var i = 0; i < 5; i++){
green_led(1);
sleep(500);
green_led(0);
sleep(500);
}
Используя Волокна, я получил синхронное поведение, работающее как ожидалось:
var Fiber = require('fibers');
function sleep(ms){
var fiber = Fiber.current;
setTimeout(function(){ fiber.run(); }, ms);
Fiber.yield();
}
function green_led(active){
//...
}
Fiber(function(){
for (var i = 0; i < 5; i++){
green_led(1);
sleep(500);
green_led(0);
sleep(500);
}
}).run();
Сложность заключается в том, как песочница кода. Необходимость использовать волокна делает это действительно сложным; Я не совсем уверен, как начать. Как я могу получить вышеупомянутую изолированную программную среду с vm2? Например, следующее явно не будет работать:
var code = "\
for (var i = 0; i < 5; i++){\
green_led(1);\
sleep(500);\
green_led(0);\
sleep(500);\
}\
";
function sleep(ms){
var fiber = Fiber.current;
setTimeout(function(){ fiber.run(); }, ms);
Fiber.yield();
}
function green_led(active){
//...
}
Fiber(function(){
vm.run(code);
}).run();
(Это не сработает, потому что green_led
а также sleep
не видны песочнице кода в виртуальной машине).
Как это должно быть сделано? Или...
- Возможно, все должно быть запущено внутри виртуальной машины, включая волокна и реализацию
green_led
так далее? - Или было бы лучше, чтобы код, выполняемый виртуальной машиной, был минимальным, а вместо этого каким-то образом включался белый список / прокси
green_led
а такжеsleep
? Не совсем легко с серым веществом, достаточно сложно понять, как в первую очередь работают волокна!
1 ответ
Это на самом деле довольно просто.
var Fiber = require('fibers');
const {VM} = require('vm2');
const vm = new VM({
sandbox: {
green_led: green_led,
sleep: sleep
}
});
function sleep(ms){
var fiber = Fiber.current;
setTimeout(function(){ fiber.run(); }, ms);
Fiber.yield();
}
function green_led(active){
//...
}
vm.run(
`Fiber(function(){
for (var i = 0; i < 5; i++){
green_led(1);
sleep(500);
green_led(0);
sleep(500);
}
}).run()`
);
Вышеупомянутый подход проходит в ссылке на Fiber
и другие функции sleep
а также green_led
через объект песочницы. Это может быть сделано другими способами. Например, sleep
а также green_led
может быть определено в строке, переданной vm.run()
а виртуальная машина могла сама include
fibers
вот так:
const {NodeVM} = require('vm2');
var vm = new NodeVM({
require: {
external: true,
}
});
vm.run(
`
var Fiber = require("fibers");
function sleep(ms){
var fiber = Fiber.current;
setTimeout(function(){ fiber.run(); }, ms);
Fiber.yield();
}
function green_led(active){
//...
}
Fiber(function(){
for (var i = 0; i < 5; i++){
green_led(1);
sleep(500);
green_led(0);
sleep(500);
}
}).run()`
);
Согласно документации, обратите внимание на разницу между VM
а также NodeVM
, Из двух приведенных выше способов только первый сможет использовать функцию тайм-аута. Кроме того, второй метод не застрахован от while (true) {}
и т.п.