使用带有代码注入而不是线程的 NodeVM 时防止无限循环
Prevent infinite loop when using NodeVM with code injection rather than threads
最近正在使用 Node.js 构建一个 API,它使用 vm2 将不受信任的代码接收到 运行。
问题是我想要 运行 异步函数,所以我需要使用不支持无限循环超时的 NodeVM
.
但是我收到的代码是一个字符串,我想防止其中出现无限循环,所以我想到了使用正则表达式来注入带有超时条件的 while/for 循环,或者抛出一个每当发生无限循环时都会发生异常。
这可能吗?
对我有用的完美解决方案是使用 AST。所以我了解了更多有关它的信息,因此我可以在任何我想要的地方注入字符串。
然后我按照以下步骤操作:
1- 使用 Esprima
解析器将字符串代码转换为 AST。
2-注入无限循环代码保护,即:
// Before any loop
let myvar = Date.now();
// Inside the loop
if (Date.now() - myvar > 1000) { break;}
使用break
或抛出错误,注意每次捕获循环时都需要一个唯一的变量名生成器。
3- 使用 escodegen
.
将其转换回字符串
您永远无法确定用户提供的代码会以良好的方式执行而不会阻塞您的节点进程。比如CPU密集型计算会阻塞主节点进程。最好的解决方案是在它自己的进程中执行此类代码,如果它没有及时完成则停止该进程。
worker-farm 是一个包,它有一个简单的 API 来启动具有可配置超时的工作进程。在这样的 worker 中执行用户提供的代码,而不是在您的主节点进程中执行。
如果你想限制用户代码使用某些库,你可以使用VM2来实现。
最近正在使用 Node.js 构建一个 API,它使用 vm2 将不受信任的代码接收到 运行。
问题是我想要 运行 异步函数,所以我需要使用不支持无限循环超时的 NodeVM
.
但是我收到的代码是一个字符串,我想防止其中出现无限循环,所以我想到了使用正则表达式来注入带有超时条件的 while/for 循环,或者抛出一个每当发生无限循环时都会发生异常。
这可能吗?
对我有用的完美解决方案是使用 AST。所以我了解了更多有关它的信息,因此我可以在任何我想要的地方注入字符串。
然后我按照以下步骤操作:
1- 使用 Esprima
解析器将字符串代码转换为 AST。
2-注入无限循环代码保护,即:
// Before any loop
let myvar = Date.now();
// Inside the loop
if (Date.now() - myvar > 1000) { break;}
使用break
或抛出错误,注意每次捕获循环时都需要一个唯一的变量名生成器。
3- 使用 escodegen
.
您永远无法确定用户提供的代码会以良好的方式执行而不会阻塞您的节点进程。比如CPU密集型计算会阻塞主节点进程。最好的解决方案是在它自己的进程中执行此类代码,如果它没有及时完成则停止该进程。
worker-farm 是一个包,它有一个简单的 API 来启动具有可配置超时的工作进程。在这样的 worker 中执行用户提供的代码,而不是在您的主节点进程中执行。
如果你想限制用户代码使用某些库,你可以使用VM2来实现。