Lưu ý: Đây vẫn là một công việc tiến bộ và một phần lấy cảm hứng từ đoạn mã của squint.
function quarantinedFunction(fnText){
var exceptionKeys=[
"eval","Object", //need exceptions for this else error. (ie, 'Exception: redefining eval is deprecated')
"Number","String","Boolean","RegExp","JSON","Date",
];
var forbiddenKeys=[
"fn","fnText","forbiddenKeys","exceptionKeys","empty","oForbiddenKeys",
];
var oForbiddenKeys=Object.create(null);
var empty=Object.create(null);
Object.freeze(empty);
forbiddenKeys.forEach(function(key){
oForbiddenKeys[key]=null;
});
[this,self].forEach(function(obj){
Object.getOwnPropertyNames(obj).forEach(function(key){
if(!key.match(/^[\$\w]+$/))return;
oForbiddenKeys[key]=null;
});
});
exceptionKeys.forEach(function(key){
delete oForbiddenKeys[key];
});
if(0){//debugging.
return function(){
return Object.keys(oForbiddenKeys);
return Object.keys(empty);
};
}
fnText=[
'"use strict";',
"var "+Object.keys(oForbiddenKeys).join(", ")+";",
"{",
fnText,
"}"
].join("\n");
var fn= (function(){
with(empty)
{
return new Function("self","window",fnText);
}
})();
return function(){
return fn.call(Object.create(null)); //self,window undefined
return fn.call(empty,empty,empty); //self,window are objects w/o properties
};
}
Output kết quả (từ Firefox nháp):
quarantinedFunction("return location.href;")();
/*
Exception: location is undefined
*/
quarantinedFunction("someGlobalVar=15;")();
/*
Exception: assignment to undeclared variable someGlobalVar
*/
quarantinedFunction("return 9*9;")();
/*
81
*/
quarantinedFunction("return console;")();
/*
undefined
*/
Và một jsfiddle với một số kết quả.
Lưu ý: Một số kết quả không mong muốn hiển thị trong phần mềm nhưng không hiển thị trong các công cụ khác (tức làBiến số location
trả về url của trang khi fiddle được xem từ aurora của firefox, nhưng không phải trên chrome hoặc trên bàn phím đầu tiên - có thể là công cụ của cơ chế __noSuchMethod__
hoặc tương tự 'cuối ràng buộc' của Firefox, dẫn đến các thuộc tính chỉ được thêm khi được truy cập).
Bạn đang cố gắng để sandbox 'eval''d/mã tùy ý? Có một cách tốt hơn xung quanh nếu đó là mục tiêu của bạn. –
Không, tôi chỉ đang nghĩ đến việc che chắn phạm vi toàn cầu từ mã người dùng. Điều này dẫn tôi đến câu hỏi này, đó là về lý thuyết. – kol
Sau đó, trong các trình duyệt hiện đại, về mặt lý thuyết, bạn có thể [đóng băng] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) đối tượng 'window'. Mặc dù tôi chưa bao giờ thử điều đó. –