是否可以读取父堆栈帧的局部变量
Is it possible to read local variables of parent stackframes?
场景:
我正在开发Javascript代码,它允许在web工作环境中运行任意用户提供的代码,类似于这种方法。让我们称双方为主机(启动工作程序)和来宾(工作程序内部)。
现在,我希望能够在worker上同时运行多个脚本,或者至少立即将它们发送给worker,而不必等待上一个脚本完成。减少延迟和开销至关重要,因为一个"会话"可能需要数百万甚至数十亿次脚本运行——几秒钟内我能做的越多越好;是的,我之所以选择Javascript是有充分理由的(性能很重要,但不是最重要的方面)。
然而,这意味着工作人员需要以某种方式可靠地告诉我脚本何时开始和停止。这需要发送一些消息,包括一个唯一的脚本标识符。
代码:
我目前正在客人中使用此代码:
onmessage = function(event) {
var scriptId = event.data.id;
var cmd = event.data.cmd;
var args = event.data.args;
switch (cmd) {
case "init":
// code here to lock down the worker and disable everything potentially insecure, except for postMessage
break;
case "run":
if (!workerInitialized()) return;
// run user given code
var code = args.code;
// ...
postMessage({cmd: "start", args: scriptId}); // signal that script started
runScript(code); // runs eval(code) with proper error reporting etc.
postMessage({cmd: "stop", args: scriptId}); // signal that script stopped
break;
// ...
}
}
问题:
如您所见,scriptId
存在于eval(code)
之上的堆栈帧中。我正在使用一些加密库来生成id,这样用户就不可能猜测id(因为工作人员会因为任何错误的猜测而死亡)。此外,onmessage
不能被code
覆盖。
当代码在code
的作者无法控制的环境中(例如,在节点服务器或不同用户的浏览器中)执行时,我可以通过在堆栈处达到峰值来确保code
不会"伪造"停止消息吗?
可能的解决方案:
在setTimeout
中发送"停止"消息,并在闭包中隐藏scriptId
,以便在code
执行完毕后立即执行。
这个JSFiddle表明它是有效的,但也许我忽略了一些邪恶的边缘案例?
这意味着,我将case "run"
代码更改为:
postMessage({cmd: "start", args: scriptId}); // signal that script started
setTimeout((function(scriptId) { return function() { postMessage({cmd: "stop", args: scriptId}); };})(scriptId), 0); // signal that script stopped, right after this function returned
scriptId = null;
runScript(code); // runs eval(code) with proper error reporting etc.
code
在任何执行环境下都不可能读取scriptId
吗?我甚至不在乎它是否能停止计时器,因为工人无论如何都会在固定的超时后被杀死(只要它不能伪造stop
消息,它就会停止"超时计时器"!)。
代码在任何执行环境中都不可能读取scriptId吗?
是的。代码只能访问其当前作用域(执行上下文)中的变量,而不能访问调用堆栈上作用域中的本地变量。
但是,eval'd代码可以访问并可能覆盖/截获全局postMessage
和onmessage
函数。如果你阻止了这种情况,他们仍然可以呼叫他们,所以你需要验证这些呼叫是否来自你的员工经理,而不是来自自定义代码。如果你已经确保了,一切都会好起来的。
请注意,当您在同一个"工作会话"中运行多个脚本时,您可能需要在每次运行后清理全局作用域(或者预先防止任何修改)。否则,独立的脚本可能能够相互通信。
- Javascript用函数return替换局部变量
- 每次调用函数时,都要修改Javascript中的局部变量
- 局部变量在闭包中丢失
- 试图将一个局部变量传递给我的ngAside控制器
- jQuery.ajax()访问javascript循环中的beforeEnd局部变量
- 其中是闭包中存储的变量-堆栈或堆
- 如何使用局部变量创建全局变量
- 如何在单击链接后将局部变量发送到部分呈现
- 定义 JavaScript 类的局部变量
- 创建所有原型函数均可访问的局部变量
- 局部变量的声明
- JavaScript:在调用之前将函数重新分配给局部变量,而不是直接调用并对'这'
- 为什么 Javascript 中的类变量在尝试多次调用它们或将它们分配给局部变量时会消失
- 函数中的局部变量
- 局部变量仍可通过函数访问
- JavaScript和局部变量是不好的做法
- 局部变量在应用 function.call() 后变为全局变量
- 如何创建一个只应用了一些过滤器的局部变量
- 我可以't克服这个错误“;未定义的局部变量或方法`f'"任何原因
- 是否可以读取父堆栈帧的局部变量