嗨:)我想知道eval
在这种情况下是否安全:
!function(){
var a = 1;
!function(){
var b = 2;
try { eval.call({}, 'a'); }
catch (e) { console.log(e.message); }
try { eval.call({}, 'b'); }
catch (e) { console.log(e.message); }
}();
}();
两次通话都失败了。这是否意味着eval
无法访问周围的范围?换句话说,使用eval.call({}, '...')
代替eval('...')
,eval
只能访问对象的成员吗?
答案 0 :(得分:2)
如果eval
没有“调用上下文” - 基本上是this
的本地值 - 那么执行上下文就是全局上下文。 Section 10.4.2 of the spec.
所以这应该有效:
!function(){
var a = 1;
function evalWrapper() {
var b = 2;
try { eval('a'); console.log("yaay!"); }
catch (e) { console.log(e.message); }
};
evalWrapper.call({});
}();
规范中描述的第一个场景是:
如果没有调用上下文或者eval代码没有被eval函数直接调用(15.1.2.1.1)评估,那么,a。将执行上下文初始化为使用eval代码作为C的全局执行上下文,如10.4.1.1中所述。
因此,除了直接调用eval( something )
之外,您所做的任何事情 - 包括,如果您阅读了引用的部分,则通过名称“eval”之外的其他内容引用“eval”函数! - 然后在全局上下文中评估字符串中的代码,包括全局词法上下文。因此,好像代码根本不在周围的功能中。
答案 1 :(得分:1)
尝试从IIFE内部访问变量。
var a = 1;
!function(){
var b = 2;
try { eval.call(null, 'console.log(a)'); }
catch (e) { console.log(e.message); }
try { eval.call(null, 'console.log(b)'); }
catch (e) { console.log(e.message); }
try { eval.call({ c: 3 }, 'console.log(c)'); }
catch (e) { console.log(e.message); }
}();
Chrome:
1
b is not defined
c is not defined
尝试从IIFE外部访问变量。考虑到Pointy的答案,除了a
之外的所有变量都应该是可访问的。
!function () {
var a = 1;
eval.call(window, [
'b = 2;',
'c = function () { return 3; };',
'd = function d() { return 4; };',
'function e() { return 5; };',
'x = function () { return a; };'
].join(' '));
}();
var l = function (a) { console.log(a); };
try { l('window.a -> ' + window.a); } catch(e) { l(e.message); };
try { l('window.b -> ' + window.b); } catch(e) { l(e.message); };
try { l('window.c() -> ' + window.c()); } catch(e) { l(e.message); };
try { l('window.d() -> ' + window.d()); } catch(e) { l(e.message); };
try { l('window.e() -> ' + window.e()); } catch(e) { l(e.message); };
try { l('window.x() -> ' + window.x()); } catch(e) { l(e.message); };
Chrome 31,FF 26,IE 8-10:
window.a -> undefined
window.b -> 2
window.c() -> 3
window.d() -> 4
window.e() -> 5
a is not defined
IE 7的行为不符合预期:
window.a -> undefined
window.b -> 2
window.c() -> 3
object doesn't support this property or method
function expected
window.x() -> 1
eval.call(window, 'function f(){return 1}')
!function () {
eval.call(window, 'function g(){return 2}');
console.log(g());
}();
console.log(f());
console.log(g());
似乎命名函数是调用eval
的范围的一部分:
2
1
g is null or undefined
实际上,"跨浏览器"意味着" Chrome 31,FF 26,IE 7-10" :)
function evil(code, success, failure) {
var head, script;
script = document.createElement('script');
script.text = [
'try{_logevil[0](eval(\'',
code.replace(/('|\\)/g, '\\\$1'),
'\'))}catch(e){_logevil[1](e);}'
].join('');
window._logevil = [success, failure];
head = document.getElementsByTagName('head')[0];
head.appendChild(script);
head.removeChild(script);
}
用法示例:
evil(
'var a = 1; alert(a); a;',
function (r) { console.log(r); },
function (e) { console.log(e.message); }
);
// prints "1"
evil(
'alert(b);',
function (r) { console.log(r); },
function (e) { console.log(e.message); }
);
// prints "b is not defined"