1

次のような信頼できないコードを 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();

( VM 内のサンドボックス化されたコードにはgreen_ledとが表示されないため、機能しません)。sleep

これはどのように行うべきですか?また...

  1. おそらく、ファイバーや実装green_ledなど、すべてを VM 内で実行する必要がありますか?
  2. それとも、VM によって実行されるコードを最小限に抑え、代わりに何らかの方法でホワイトリスト/プロキシを使用する方がよいでしょうgreen_ledsleep? そもそも繊維がどのように機能するかを理解するのは非常に困難です。
4

1 に答える 1

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他の関数への参照を渡します。これは他の方法で行うことができます。たとえば、andは に渡される文字列内で定義でき、vm 自体は次のようになります。sleepgreen_ledsleepgreen_ledvm.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ください。上記の 2 つの方法のうち、タイムアウト機能を利用できるのは最初の方法だけです。また、2番目の方法は、while (true) {}などの影響を受けません。

于 2016-12-10T23:15:39.390 に答える