是否可以读取父堆栈的局部变量? [英] Is it possible to read local variables of parent stackframes?

查看:139
本文介绍了是否可以读取父堆栈的局部变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景

我正在开发允许在Web工作环境中运行任意用户提供的代码的Javascript代码,类似于< a href =https://stackoverflow.com/questions/10653809/making-webworkers-a-safe-environment/>这种方法。让我们调用双方主持人(启动工作人员)和访客(工作人员内部)。

I am working on Javascript code that allows running arbitrary user-supplied code in a web worker environment, similar to this approach. Let's call the two parties host (launches the worker) and guest (inside the worker).

现在,我希望能够在工作人员上运行多个脚本同时,或者至少将它们立即发送给工作人员,而不必等待之前的脚本完成。减少延迟和开销至关重要,因为单个会话可能需要数百万甚至数十亿的脚本运行 - 我能在几秒钟内做得越多越好;是的,有一个很好的理由为什么我选择Javascript(性能很重要,但不是最重要的方面)。

Now, I want to be able to run multiple scripts on the worker at the same time, or at least have them sent to the worker right away, without having to wait for the previous script to finish. It is crucial to reduce delay and overhead because a single "session" could take millions or even billions of script runs - the more I can do in a few seconds the better; and yes, there is a good reason as to why I am choosing Javascript (performance is important, but not the most important aspect).

然而,这意味着工人不知何故,需要在脚本启动和停止时可靠地告诉我。这需要一些消息发送,涉及唯一的脚本标识符。

However, that means that the worker somehow needs to reliably tell me when a script started and stopped. That requires some message sending, involving a unique script identifier.

代码

我目前在访客中使用此代码:

I am currently using this code in the guest:

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 存在于<$ c $以上的堆栈框架中C>的eval(代码)。我正在使用一些加密库来生成id,因此用户无法猜测id(因为工作人员在任何错误的猜测时被杀死)。此外, onmessage 无法被代码覆盖。

As you can see, scriptId exists in a stackframe above eval(code). I am using some cryptographic library to generate the id so the user cannot possibly guess the id (since the worker gets killed upon any wrong guess). Also, onmessage cannot be overridden by code.

我是否可以确保代码无法伪造停止消息,当代码在的作者环境中执行时,会在堆栈处达到峰值代码无法控制(例如在节点服务器上或在其他用户的浏览器中)?

Can I make sure that code cannot "fake" the stop message, by peaking at the stack when the code is executed in an environment that the author of code cannot control (e.g. on a node server or in the browser of a different user)?

可能的解决方案

setTimeout 中发送停止消息并隐藏 scriptId 处于关闭状态,因此它将在代码完成执行后立即执行。

Send the "stop" message in setTimeout and hide scriptId in closure so it will be executed right after code finished execution.

这个JSFiddle 显示它有效,但也许我忽略了一些邪恶的边缘情况?

This JSFiddle shows that it works, but maybe I am overlooking some evil edge cases?

这意味着,我将案例run代码更改为:

That means, I change the case "run" code to this:

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.

<$ c $是不可能的c>代码在任何执行环境中读取 scriptId ?我甚至不关心它是否可以停止计时器,因为工作人员无论如何都会在固定超时后被杀死(只要它不能伪造停止消息就会停止那个超时计时器!)。

Is it impossible for code to read scriptId in any execution environment? I don't even care if it can stop the timer, because the worker will be killed after a fixed timeout anyway (as long as it cannot fake the stop message which will stop that "timeout timer"!).

推荐答案


代码无法在任何地方读取scriptId执行环境?

is not possible for code to read scriptId in any execution environment?

是的。代码只能访问当前范围内的变量(执行上下文),而不是本地变量调用堆栈上的范围。

Yes. Code can only access variables in its current scope (of the execution context), not local variables from scopes on the call stack.

但是,eval'd代码可以访问并可能覆盖/拦截全局 postMessage onmessage 函数。如果您已经阻止它,他们仍然可以调用它们,因此您需要验证调用来自您的工作管理器而不是来自自定义代码。如果你已经确定了,一切都应该没问题。

However, eval'd code can access and possibly overwrite/intercept the global postMessage and onmessage functions. If you have prevented that, they still would be able to call them, so you need to verify that the calls came from your worker manager and not from the custom code. If you have ensured that, everything should be fine.

请注意,当你在同一个工作会话中运行多个脚本时,你可能需要清理每次运行后的全局范围(或​​防止事先进行任何修改)。否则,独立脚本可能能够相互通信。

Notice that when you're running multiple scripts in the same "worker session", you might need to clean up the global scope after each run (or prevent any modifications in beforehand). Otherwise, independent scripts might be able to communicate with each other.

这篇关于是否可以读取父堆栈的局部变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆