kangax <> writes:
> On 2/22/10 12:03 PM, Lasse Reichstein Nielsen wrote:
>> kangax<> writes:
>>
>>> If I'm reading spec correctly, one of the ways to get global object
>>> from within _any_ code in ES5 is by using indirect call to eval.
>>
>> Not if there is another variable called "eval" in scope.
>
> But, AIUI, you can't have another variable named eval in strict mode
No, but you can create a shadowing binding before entering strict mode, e.g.,
// Non-strict context.
function myEval(s) { "use strict"; return eval(s); }
function shadower() {
var eval = myEval;
return function context(){
"use strict";
<< your code inserted here >>
}();
}
shadower();
>> If you are certain to have access to "eval" on the global object, you
>> are pretty close to haveing the global object itself.
>>
>> Another approach is Function("return this")(), but Function may be
>
> That was my first thought as well, but from what I can see, this won't
> "work". It looks like `Function('return this')()` won't give you a
> global object.
True, my mistake. The function's scope will be the global environment,
but it will create a new scope when it's called, just as any other
function.
> Or did I miss something?
No, not as far as I can see.
However, the Function constructor can create non-strict functions in
a strict environment, so this should work:
var global = Function("return function(){return this;}();")();
A determined jailer will be able to prevent that too, by changing
the binding of Function and Function.prototype.constructor:
var myFunction = function(oldFunction) {
var myFunction = function Function(args) {
var arr = Array.prototype.slice.call(args, 0, args.length);
arr[arr.length-1] = '"use strict";\n' + arr[arr.length-1];
return oldFunction.apply(null, arr);
};
Function.prototype.constructor = myFunction;
return myFunction;
}(Function);
function myEval(s) { "use strict"; return eval(s); }
function shadower() {
var eval = myEval;
var Function = myFunction;
return function() {
"use strict";
<< Your code, in jail >>
}();
}
I'm sure there are still holes in this (e.g., setTimeout with string
argument), but the idea is to prevent you from getting access to
running non-strict code in any way. That will also prevent you from
getting direct access to the global object.
You will actually need to shadow access to ANY non-frozen object on
the global object - because if "foo" refers to an property of the
global object, then
foo.bar = function() { return this; }
var global = foo.bar();
would work.
Strict mode is build so that you can't access strict mode variables
from non-strict code. You are still allowed to create non-strict code,
but only as if the code was running in the global environment.
/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'