[英]How do I prevent accidental global name space pollution with javascript eval?
我正在用JavaScript编写一个简单的REPL(读取,评估,打印,循环)实现。 我可以隔离代码并调用上下文,如下所示:
var sandbox = {
// Allow the input code to use predefined helper functions
// without the preceding use of the this keyword.
helper_fn: function() { alert("foo"); }
};
var func = new Function("with (this) { " + user_inputed_code + " }");
func.call(sandbox);
现在它关闭user_inputed_code
使this
参照网址到sandbox
,如果输入的代码访问或变异this
很影响sandbox
。
但是,我注意到如果插入的代码意外忘记用关键字var
作为变量赋值的序言,那么全局命名空间会被污染。
反正有没有阻止这个? 如果是这样(也许是正则表达式?)? 有没有更好的方法来解决这个问题?
我将提供两种完全不同于其他人在此讨论的方法。 它们都很激烈,并且在您想要相对隔离环境时非常有用。
更具体地说,如果您正在构建REPL,请查看我们讨论的这个答案 ,并解释如何使用iframe的第一种方法在同一范围内但在全局范围之外评估代码。
(我假设一个浏览器,在节点中你可以简单地使用vm模块并在runInContext中选择上下文)
事实证明,有一种方法是"use strict"
而没有Object.freeze
。 您必须使用自己的沙箱对象手动替换全局命名空间:
var sandbox, module, func, output;
// Empty object or with defined methods / properties
// you want to expose as globals.
sandbox = {};
// A reference to an object you WANT to provide safe
// access to. In this example it's just an empty object.
module = {};
// A better version of eval:
func = new Function("module", "with(this){return(function(module,global,window){\"use strict\";return eval(\"" + code + "\");})(module,this,this)}");
output = func.call(sandbox, module);
此代码允许全局和窗口引用沙盒对象而不是全局名称空间。 它伪装变量global
和window
作为沙箱对象,如果输入错过了var
的使用,使用"use strict"
将导致它抛出异常。 它还将函数包装在with
语句中,以使沙箱对象中定义的方法和属性工作,就像它们之前一样this.
。 要查看实现示例(带有测试规范),请查看此要点 。
谢谢大家的意见。 希望这个答案能帮助别人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.